%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% core compiler and runtime
%
% This file is part of Logtalk
% SPDX-FileCopyrightText: 1998-2024 Paulo Moura
% SPDX-License-Identifier: Apache-2.0
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% operator declarations
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% message sending and super call operators
% message sending to an explicit object
:- op(600, xfy, ::).
% message sending to "self"
:- op(600, fy, ::).
% "super" call (calls an inherited or imported method definition)
:- op(600, fy, ^^).
% mode operators
% input argument (instantiated); ISO Prolog standard operator
:- op(200, fy, (+)).
% input/output argument
:- op(200, fy, (?)).
% input argument (not modified by the call)
:- op(200, fy, (@)).
% output argument (not instantiated); ISO Prolog standard operator
:- op(200, fy, (-)).
% ground argument
:- op(200, fy, ++).
% unbound argument (typically when returning an opaque term)
:- op(200, fy, --).
% bitwise left-shift operator (used for context-switching calls)
% some backend Prolog compilers don't declare this ISO Prolog standard operator!
:- op(400, yfx, <<).
% bitwise right-shift operator (used for lambda expressions)
% some backend Prolog compilers don't declare this ISO Prolog standard operator!
:- op(400, yfx, >>).
% predicate alias operator (alternative to the ::/2 or :/2 operators depending on the context)
% first introduced in SWI-Prolog and YAP also for defining aliases to module predicates
:- op(700, xfx, as).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% runtime directives (bookkeeping tables)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% tables of defined events and monitors
% '$lgt_before_event_'(Obj, Msg, Sender, Monitor, Call)
:- dynamic('$lgt_before_event_'/5).
% '$lgt_after_event_'(Obj, Msg, Sender, Monitor, Call)
:- dynamic('$lgt_after_event_'/5).
% tables of loaded entities, entity and predicate properties, plus entity relations
% '$lgt_current_protocol_'(Ptc, Prefix, Dcl, Rnm, Flags)
:- multifile('$lgt_current_protocol_'/5).
:- dynamic('$lgt_current_protocol_'/5).
% '$lgt_current_category_'(Ctg, Prefix, Dcl, Def, Rnm, Flags)
:- multifile('$lgt_current_category_'/6).
:- dynamic('$lgt_current_category_'/6).
% '$lgt_current_object_'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, Flags)
:- multifile('$lgt_current_object_'/11).
:- dynamic('$lgt_current_object_'/11).
% '$lgt_entity_property_'(Entity, Property)
:- multifile('$lgt_entity_property_'/2).
:- dynamic('$lgt_entity_property_'/2).
% '$lgt_predicate_property_'(Entity, Functor/Arity, Property)
:- multifile('$lgt_predicate_property_'/3).
:- dynamic('$lgt_predicate_property_'/3).
% '$lgt_implements_protocol_'(ObjOrCtg, Ptc, Scope)
:- multifile('$lgt_implements_protocol_'/3).
:- dynamic('$lgt_implements_protocol_'/3).
% '$lgt_imports_category_'(Obj, Ctg, Scope)
:- multifile('$lgt_imports_category_'/3).
:- dynamic('$lgt_imports_category_'/3).
% '$lgt_instantiates_class_'(Instance, Class, Scope)
:- multifile('$lgt_instantiates_class_'/3).
:- dynamic('$lgt_instantiates_class_'/3).
% '$lgt_specializes_class_'(Class, Superclass, Scope)
:- multifile('$lgt_specializes_class_'/3).
:- dynamic('$lgt_specializes_class_'/3).
% '$lgt_extends_category_'(Ctg, ExtCtg, Scope)
:- multifile('$lgt_extends_category_'/3).
:- dynamic('$lgt_extends_category_'/3).
% '$lgt_extends_object_'(Prototype, Parent, Scope)
:- multifile('$lgt_extends_object_'/3).
:- dynamic('$lgt_extends_object_'/3).
% '$lgt_extends_protocol_'(Ptc, ExtPtc, Scope)
:- multifile('$lgt_extends_protocol_'/3).
:- dynamic('$lgt_extends_protocol_'/3).
% '$lgt_complemented_object_'(Obj, Ctg, Dcl, Def, Rnm)
:- dynamic('$lgt_complemented_object_'/5).
% '$lgt_uses_predicate_'(Entity, Obj, Original, Alias, Ctx)
:- multifile('$lgt_uses_predicate_'/5).
% '$lgt_use_module_predicate_'(Entity, Module, Original, Alias, Ctx)
:- multifile('$lgt_use_module_predicate_'/5).
% table of loaded files
% '$lgt_loaded_file_'(Basename, Directory, Mode, Flags, TextProperties, ObjectFile, TimeStamp)
:- multifile('$lgt_loaded_file_'/7).
:- dynamic('$lgt_loaded_file_'/7).
% '$lgt_included_file_'(File, MainBasename, MainDirectory, TimeStamp)
:- multifile('$lgt_included_file_'/4).
:- dynamic('$lgt_included_file_'/4).
% '$lgt_failed_file_'(SourceFile)
:- dynamic('$lgt_failed_file_'/1).
% '$lgt_parent_file_'(SourceFile, ParentSourceFile)
:- dynamic('$lgt_parent_file_'/2).
% '$lgt_file_loading_stack_'(SourceFile, Directory)
:- dynamic('$lgt_file_loading_stack_'/2).
% runtime flag values
% '$lgt_current_flag_'(Name, Value)
:- dynamic('$lgt_current_flag_'/2).
% static binding caches
% '$lgt_send_to_obj_static_binding_'(Obj, Pred, ExCtx, Call)
:- dynamic('$lgt_send_to_obj_static_binding_'/4).
% dynamic binding lookup caches for messages and super calls
% '$lgt_send_to_obj_'(Obj, Pred, ExCtx)
:- dynamic('$lgt_send_to_obj_'/3).
% '$lgt_send_to_obj_ne_'(Obj, Pred, ExCtx)
:- dynamic('$lgt_send_to_obj_ne_'/3).
% '$lgt_send_to_self_'(Obj, Pred, ExCtx)
:- dynamic('$lgt_send_to_self_'/3).
% '$lgt_obj_super_call_'(Super, Pred, ExCtx)
:- dynamic('$lgt_obj_super_call_'/3).
% '$lgt_ctg_super_call_'(Ctg, Pred, ExCtx)
:- dynamic('$lgt_ctg_super_call_'/3).
% dynamic binding lookup cache for asserting and retracting dynamic facts
% '$lgt_db_lookup_cache_'(Obj, Fact, Sender, TFact, UpdateData)
:- dynamic('$lgt_db_lookup_cache_'/5).
% table of library paths
% logtalk_library_path(Library, Path)
:- multifile(logtalk_library_path/2).
:- dynamic(logtalk_library_path/2).
% extension point for logtalk_make/1
% logtalk_make_target_action(Target)
:- multifile(logtalk_make_target_action/1).
:- dynamic(logtalk_make_target_action/1).
% extension point for the linter
% logtalk_linter_hook(Goal, Flag, File, Lines, Type, Entity, Warning)
:- multifile(logtalk_linter_hook/7).
% term- and goal-expansion default compiler hooks
% '$lgt_hook_term_expansion_'(Term, ExpandedTerms)
:- dynamic('$lgt_hook_term_expansion_'/2).
% '$lgt_hook_goal_expansion_'(Goal, ExpandedGoal)
:- dynamic('$lgt_hook_goal_expansion_'/2).
% engines
% '$lgt_current_engine_'(Object, Engine, TermQueue, Id)
:- dynamic('$lgt_current_engine_'/4).
% counters
% '$lgt_dynamic_entity_counter_'(Kind, Base, Count)
:- dynamic('$lgt_dynamic_entity_counter_'/3).
% '$lgt_threaded_tag_counter_'(Tag)
:- dynamic('$lgt_threaded_tag_counter_'/1).
% '$lgt_threaded_engine_tag_counter_'(Tag)
:- dynamic('$lgt_threaded_engine_tag_counter_'/1).
% debugging hook predicates
:- multifile('$logtalk#0.trace_event#2'/3).
:- dynamic('$logtalk#0.trace_event#2'/3).
:- multifile('$logtalk#0.debug_handler#1'/2).
:- multifile('$logtalk#0.debug_handler#3'/4).
% internal initialization flags
:- dynamic('$lgt_built_in_entities_loaded_'/0).
:- dynamic('$lgt_runtime_initialization_completed_'/0).
% user-defined flags
% '$lgt_user_defined_flag_'(Flag, Access, Type)
:- dynamic('$lgt_user_defined_flag_'/3).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% compiler directives
%
% (used for source file compilation and runtime creation of new entities)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_pp_file_compiler_flag_'(Name, Value)
:- dynamic('$lgt_pp_file_compiler_flag_'/2).
% '$lgt_pp_entity_compiler_flag_'(Name, Value)
:- dynamic('$lgt_pp_entity_compiler_flag_'/2).
% '$lgt_pp_dcl_'(Clause)
:- dynamic('$lgt_pp_dcl_'/1).
% '$lgt_pp_def_'(Clause)
:- dynamic('$lgt_pp_def_'/1).
% '$lgt_pp_ddef_'(Clause)
:- dynamic('$lgt_pp_ddef_'/1).
% '$lgt_pp_super_'(Clause)
:- dynamic('$lgt_pp_super_'/1).
% '$lgt_pp_synchronized_'(Head, Mutex, File, Lines)
:- dynamic('$lgt_pp_synchronized_'/4).
% '$lgt_pp_predicate_mutex_counter_'(Count)
:- dynamic('$lgt_pp_predicate_mutex_counter_'/1).
% '$lgt_pp_dynamic_'(Head, Original, File, Lines)
:- dynamic('$lgt_pp_dynamic_'/4).
% '$lgt_pp_discontiguous_'(Head, File, Lines)
:- dynamic('$lgt_pp_discontiguous_'/3).
% '$lgt_pp_mode_'(Mode, Determinism, File, Lines)
:- dynamic('$lgt_pp_mode_'/4).
% '$lgt_pp_public_'(Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_public_'/4).
% '$lgt_pp_protected_'(Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_protected_'/4).
% '$lgt_pp_private_'(Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_private_'/4).
% '$lgt_pp_meta_predicate_'(PredTemplate, MetaTemplate, File, Lines)
:- dynamic('$lgt_pp_meta_predicate_'/4).
% '$lgt_pp_predicate_alias_'(Entity, Pred, Alias, NonTerminalFlag, File, Lines)
:- dynamic('$lgt_pp_predicate_alias_'/6).
% '$lgt_pp_non_terminal_'(Functor, Arity, ExtArity)
:- dynamic('$lgt_pp_non_terminal_'/3).
% '$lgt_pp_multifile_'(Head, Original, File, Lines)
:- dynamic('$lgt_pp_multifile_'/4).
% '$lgt_pp_coinductive_'(Head, TestHead, HeadExCtx, TCHead, BodyExCtx, THead, DHead, File, Lines)
:- dynamic('$lgt_pp_coinductive_'/9).
% '$lgt_pp_coinductive_head_'(Head, HeadExCtx, TCHead)
:- dynamic('$lgt_pp_coinductive_head_'/3).
% '$lgt_pp_object_'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, Flags)
:- dynamic('$lgt_pp_object_'/11).
% '$lgt_pp_category_'(Ctg, Prefix, Dcl, Def, Rnm, Flags)
:- dynamic('$lgt_pp_category_'/6).
% '$lgt_pp_protocol_'(Ptc, Prefix, Dcl, Rnm, Flags)
:- dynamic('$lgt_pp_protocol_'/5).
% '$lgt_pp_entity_'(Type, Entity, Prefix)
:- dynamic('$lgt_pp_entity_'/3).
% '$lgt_pp_module_'(Module)
:- dynamic('$lgt_pp_module_'/1).
% '$lgt_pp_entity_lines_'(Entity, Lines)
:- dynamic('$lgt_pp_entity_lines_'/2).
% '$lgt_pp_parameter_variables_'(ParameterVariables)
:- dynamic('$lgt_pp_parameter_variables_'/1).
% '$lgt_pp_object_alias_'(Obj, Alias, CompilationContext, File, Lines)
:- dynamic('$lgt_pp_object_alias_'/5).
% '$lgt_pp_module_alias_'(Module, Alias, CompilationContext, File, Lines)
:- dynamic('$lgt_pp_module_alias_'/5).
% '$lgt_pp_uses_predicate_'(Obj, Predicate, Alias, CompilationContext, File, Lines)
:- dynamic('$lgt_pp_uses_predicate_'/6).
% '$lgt_pp_uses_non_terminal_'(Obj, NonTerminal, NonTerminalAlias, Predicate, PredicateAlias, CompilationContext, File, Lines)
:- dynamic('$lgt_pp_uses_non_terminal_'/8).
% '$lgt_pp_use_module_predicate_'(Module, Predicate, Alias, CompilationContext, File, Lines)
:- dynamic('$lgt_pp_use_module_predicate_'/6).
% '$lgt_pp_use_module_non_terminal_'(Module, NonTerminal, NonTerminalAlias, Predicate, PredicateAlias, CompilationContext, File, Lines)
:- dynamic('$lgt_pp_use_module_non_terminal_'/8).
% '$lgt_pp_entity_info_'(List, File, Lines)
:- dynamic('$lgt_pp_entity_info_'/3).
% '$lgt_pp_predicate_info_'(Predicate, List, File, Lines)
:- dynamic('$lgt_pp_predicate_info_'/4).
% '$lgt_pp_implemented_protocol_'(Ptc, ObjOrCtg, Prefix, Dcl, Scope)
:- dynamic('$lgt_pp_implemented_protocol_'/5).
% '$lgt_pp_imported_category_'(Ctg, Obj, Prefix, Dcl, Def, Scope)
:- dynamic('$lgt_pp_imported_category_'/6).
% '$lgt_pp_extended_object_'(Parent, Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Scope)
:- dynamic('$lgt_pp_extended_object_'/11).
% '$lgt_pp_instantiated_class_'(Class, Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Scope)
:- dynamic('$lgt_pp_instantiated_class_'/11).
% '$lgt_pp_specialized_class_'(Superclass, Class, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Scope)
:- dynamic('$lgt_pp_specialized_class_'/11).
% '$lgt_pp_extended_protocol_'(ExtPtc, Ptc, Prefix, Dcl, Scope)
:- dynamic('$lgt_pp_extended_protocol_'/5).
% '$lgt_pp_extended_category_'(ExtCtg, Ctg, Prefix, Dcl, Def, Scope)
:- dynamic('$lgt_pp_extended_category_'/6).
% '$lgt_pp_complemented_object_'(Obj, Ctg, Dcl, Def, Rnm)
:- dynamic('$lgt_pp_complemented_object_'/5).
% '$lgt_pp_file_initialization_'(Goal, Lines)
:- dynamic('$lgt_pp_file_initialization_'/2).
% '$lgt_pp_file_entity_initialization_'(Object, Goal, Lines)
:- dynamic('$lgt_pp_file_entity_initialization_'/3).
% '$lgt_pp_object_initialization_'(Goal, SourceData, Lines)
:- dynamic('$lgt_pp_object_initialization_'/3).
% '$lgt_pp_final_object_initialization_'(Goal, Lines)
:- dynamic('$lgt_pp_final_object_initialization_'/2).
% '$lgt_pp_entity_meta_directive_'(Directive, SourceData, Lines)
:- dynamic('$lgt_pp_entity_meta_directive_'/3).
% '$lgt_pp_redefined_built_in_'(Head, ExCtx, THead)
:- dynamic('$lgt_pp_redefined_built_in_'/3).
% '$lgt_pp_directive_'(Directive)
:- dynamic('$lgt_pp_directive_'/1).
% '$lgt_pp_prolog_term_'(Term, Lines)
:- dynamic('$lgt_pp_prolog_term_'/2).
% '$lgt_pp_entity_term_'(Term, SourceData, Lines)
:- dynamic('$lgt_pp_entity_term_'/3).
% '$lgt_pp_final_entity_term_'(Term, Lines)
:- dynamic('$lgt_pp_final_entity_term_'/2).
% '$lgt_pp_entity_aux_clause_'(Clause)
:- dynamic('$lgt_pp_entity_aux_clause_'/1).
% '$lgt_pp_final_entity_aux_clause_'(Clause)
:- dynamic('$lgt_pp_final_entity_aux_clause_'/1).
% '$lgt_pp_number_of_clauses_rules_'(Functor, Arity, NumberOfClauses, NumberOfRules)
:- dynamic('$lgt_pp_number_of_clauses_rules_'/4).
% '$lgt_pp_number_of_clauses_rules_'(Other, Functor, Arity, NumberOfClauses, NumberOfRules)
:- dynamic('$lgt_pp_number_of_clauses_rules_'/5).
% '$lgt_pp_predicate_declaration_location_'(Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_predicate_declaration_location_'/4).
% '$lgt_pp_predicate_definition_location_'(Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_predicate_definition_location_'/4).
% '$lgt_pp_defines_predicate_'(Head, Functor/Arity, ExCtx, THead, Mode, Origin)
:- dynamic('$lgt_pp_defines_predicate_'/6).
% '$lgt_pp_inline_predicate_'(Functor/Arity)
:- dynamic('$lgt_pp_inline_predicate_'/1).
% '$lgt_pp_predicate_definition_location_'(Other, Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_predicate_definition_location_'/5).
% '$lgt_pp_non_tail_recursive_predicate_'(Functor, Arity, File, Lines)
:- dynamic('$lgt_pp_non_tail_recursive_predicate_'/4).
% '$lgt_pp_predicate_recursive_calls_'(Functor, Arity, Counter)
:- dynamic('$lgt_pp_predicate_recursive_calls_'/3).
% '$lgt_pp_calls_predicate_'(Functor/Arity, TFunctor/TArity, HeadFunctor/HeadArity, File, Lines)
:- dynamic('$lgt_pp_calls_predicate_'/5).
% '$lgt_pp_calls_self_predicate_'(Functor/Arity, HeadFunctor/HeadArity, File, Lines)
:- dynamic('$lgt_pp_calls_self_predicate_'/4).
% '$lgt_pp_calls_super_predicate_'(Functor/Arity, HeadFunctor/HeadArity, File, Lines)
:- dynamic('$lgt_pp_calls_super_predicate_'/4).
% '$lgt_pp_updates_predicate_'(Dynamic, HeadFunctor/HeadArity, File, Lines)
:- dynamic('$lgt_pp_updates_predicate_'/4).
% '$lgt_pp_non_portable_predicate_'(Head, File, Lines)
:- dynamic('$lgt_pp_non_portable_predicate_'/3).
% '$lgt_pp_non_portable_function_'(Function, File, Lines)
:- dynamic('$lgt_pp_non_portable_function_'/3).
% '$lgt_pp_missing_function_'(Function, File, Lines)
:- dynamic('$lgt_pp_missing_function_'/3).
% '$lgt_pp_missing_meta_predicate_directive_'(Head, File, Lines)
:- dynamic('$lgt_pp_missing_meta_predicate_directive_'/3).
% '$lgt_pp_missing_dynamic_directive_'(Head, File, Lines)
:- dynamic('$lgt_pp_missing_dynamic_directive_'/3).
% '$lgt_pp_missing_discontiguous_directive_'(Head, File, Lines)
:- dynamic('$lgt_pp_missing_discontiguous_directive_'/3).
% '$lgt_pp_missing_multifile_directive_'(PI, File, Lines)
:- dynamic('$lgt_pp_missing_multifile_directive_'/3).
% '$lgt_pp_missing_use_module_directive_'(Module, Functor/Arity)
:- dynamic('$lgt_pp_missing_use_module_directive_'/2).
% '$lgt_pp_previous_predicate_'(Head, Mode)
:- dynamic('$lgt_pp_previous_predicate_'/2).
% '$lgt_pp_defines_non_terminal_'(Functor, Arity, ExtArity)
:- dynamic('$lgt_pp_defines_non_terminal_'/3).
% '$lgt_pp_calls_non_terminal_'(Functor, Arity, ExtArity, Lines)
:- dynamic('$lgt_pp_calls_non_terminal_'/4).
% '$lgt_pp_referenced_object_'(Object, File, Lines)
:- dynamic('$lgt_pp_referenced_object_'/3).
% '$lgt_pp_referenced_protocol_'(Protocol, File, Lines)
:- dynamic('$lgt_pp_referenced_protocol_'/3).
% '$lgt_pp_referenced_category_'(Category, File, Lines)
:- dynamic('$lgt_pp_referenced_category_'/3).
% '$lgt_pp_referenced_module_'(Module, File, Lines)
:- dynamic('$lgt_pp_referenced_module_'/3).
% '$lgt_pp_referenced_object_message_'(Object, Functor/Arity, AliasFunctor/AliasArity, HeadFunctor/HeadArity, File, Lines)
:- dynamic('$lgt_pp_referenced_object_message_'/6).
% '$lgt_pp_referenced_module_predicate_'(Module, Functor/Arity, AliasFunctor/AliasArity, HeadFunctor/HeadArity, File, Lines)
:- dynamic('$lgt_pp_referenced_module_predicate_'/6).
% '$lgt_pp_global_operator_'(Priority, Specifier, Operator)
:- dynamic('$lgt_pp_global_operator_'/3).
% '$lgt_pp_file_operator_'(Priority, Specifier, Operator)
:- dynamic('$lgt_pp_file_operator_'/3).
% '$lgt_pp_entity_operator_'(Priority, Specifier, Operator, Scope, File, Lines)
:- dynamic('$lgt_pp_entity_operator_'/6).
% '$lgt_pp_warnings_top_goal_'(Goal)
:- dynamic('$lgt_pp_warnings_top_goal_'/1).
% '$lgt_pp_compiling_warnings_counter_'(Counter)
:- dynamic('$lgt_pp_compiling_warnings_counter_'/1).
% '$lgt_pp_loading_warnings_counter_'(Counter)
:- dynamic('$lgt_pp_loading_warnings_counter_'/1).
% '$lgt_pp_hook_term_expansion_'(Term, Terms)
:- dynamic('$lgt_pp_hook_term_expansion_'/2).
% '$lgt_pp_hook_goal_expansion_'(Goal, ExpandedGoal)
:- dynamic('$lgt_pp_hook_goal_expansion_'/2).
% '$lgt_pp_built_in_'
:- dynamic('$lgt_pp_built_in_'/0).
% '$lgt_pp_dynamic_'
:- dynamic('$lgt_pp_dynamic_'/0).
% '$lgt_pp_threaded_'
:- dynamic('$lgt_pp_threaded_'/0).
% '$lgt_pp_file_encoding_'(SourceFile, LogtalkEncoding, PrologEncoding, Line)
:- dynamic('$lgt_pp_file_encoding_'/4).
% '$lgt_pp_file_bom_'(SourceFile, BOM)
:- dynamic('$lgt_pp_file_bom_'/2).
% '$lgt_pp_file_paths_flags_'(Basename, Directory, SourceFile, ObjectFile, Flags)
:- dynamic('$lgt_pp_file_paths_flags_'/5).
% '$lgt_pp_runtime_clause_'(Clause)
:- dynamic('$lgt_pp_runtime_clause_'/1).
% '$lgt_pp_cc_if_found_'(Goal)
:- dynamic('$lgt_pp_cc_if_found_'/1).
% '$lgt_pp_cc_skipping_'
:- dynamic('$lgt_pp_cc_skipping_'/0).
% '$lgt_pp_cc_mode_'(Action)
:- dynamic('$lgt_pp_cc_mode_'/1).
% '$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines)
:- dynamic('$lgt_pp_term_source_data_'/5).
% '$lgt_pp_aux_predicate_counter_'(Counter)
:- dynamic('$lgt_pp_aux_predicate_counter_'/1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% top-level interpreter versions of the message sending and context
% switching call control constructs
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% top-level interpreter message sending calls
Obj::Pred :-
var(Obj),
'$lgt_execution_context'(ExCtx, user, user, user, Obj, [], []),
throw(error(instantiation_error, logtalk(Obj::Pred, ExCtx))).
{Obj}::Pred :-
!,
% use current default value of the "events" flag
'$lgt_current_flag_'(events, Events),
'$lgt_comp_ctx'(Ctx, _, _, user, user, user, Obj, _, [], [], ExCtx, runtime, [], _, _),
'$lgt_execution_context'(ExCtx, user, user, user, Obj, [], []),
catch(
'$lgt_compile_message_to_object'(Pred, {Obj}, Call, Events, Ctx),
Error,
'$lgt_runtime_error_handler'(error(Error, logtalk({Obj}::Pred, ExCtx)))
),
( nonvar(Obj),
'$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 512 =:= 512 ->
% object compiled in debug mode
catch('$lgt_debug'(top_goal({Obj}::Pred, Call), ExCtx), Error, '$lgt_runtime_error_handler'(Error))
; % object not compiled in debug mode or non-existing object or invalid object identifier
catch(Call, Error, '$lgt_runtime_error_handler'(Error))
).
Obj::Pred :-
% use current default value of the "events" flag
'$lgt_current_flag_'(events, Events),
'$lgt_comp_ctx'(Ctx, _, _, user, user, user, Obj, _, [], [], ExCtx, runtime, [], _, _),
'$lgt_execution_context'(ExCtx, user, user, user, Obj, [], []),
catch(
'$lgt_compile_message_to_object'(Pred, Obj, Call, Events, Ctx),
Error,
'$lgt_runtime_error_handler'(error(Error, logtalk(Obj::Pred, ExCtx)))
),
( '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 512 =:= 512 ->
% object compiled in debug mode
catch('$lgt_debug'(top_goal(Obj::Pred, Call), ExCtx), Error, '$lgt_runtime_error_handler'(Error))
; % object not compiled in debug mode or non-existing object
catch(Call, Error, '$lgt_runtime_error_handler'(Error))
).
% top-level interpreter context-switch calls (debugging control construct)
Obj<
% object compiled in debug mode
catch('$lgt_debug'(top_goal({Obj}<
% object compiled in debug mode
catch('$lgt_debug'(top_goal(Obj<
'$lgt_runtime_normalized_error_handler'(NormalizedError)
; '$lgt_runtime_normalized_error_handler'(Error)
).
'$lgt_runtime_normalized_error_handler'(error(existence_error(procedure, ':'(Module,PI)), Context)) :-
% assuming we're running with a backend compiler supporting modules,
% check that the error is the context of the module where Logtalk is loaded
atom(Module),
'$lgt_user_module_qualification'(xx, ':'(Module,xx)),
!,
'$lgt_runtime_normalized_error_handler'(error(existence_error(procedure, PI), Context)).
'$lgt_runtime_normalized_error_handler'(error(existence_error(procedure, TFunctor/6), _)) :-
( atom_concat(Prefix, '_idcl', TFunctor) ->
true
; atom_concat(Prefix, '_dcl', TFunctor)
),
'$lgt_prefix_to_entity'(Prefix, Obj),
( '$lgt_instantiates_class_'(_, Obj, _)
; '$lgt_specializes_class_'(_, Obj, _)
; '$lgt_extends_object_'(_, Obj, _)
; '$lgt_complemented_object_'(Obj, _, _, _, _)
),
\+ '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _),
throw(error(existence_error(object, Obj), logtalk(_, _))).
'$lgt_runtime_normalized_error_handler'(error(existence_error(procedure, TFunctor/5), _)) :-
atom_concat(Prefix, '_dcl', TFunctor),
'$lgt_prefix_to_entity'(Prefix, CtgOrPtc),
( '$lgt_implements_protocol_'(_, CtgOrPtc, _), \+ '$lgt_current_protocol_'(CtgOrPtc, _, _, _, _),
throw(error(existence_error(protocol, CtgOrPtc), logtalk(_, _)))
; '$lgt_extends_protocol_'(_, CtgOrPtc, _), \+ '$lgt_current_protocol_'(CtgOrPtc, _, _, _, _),
throw(error(existence_error(protocol, CtgOrPtc), logtalk(_, _)))
; '$lgt_imports_category_'(_, CtgOrPtc, _), \+ '$lgt_current_category_'(CtgOrPtc, _, _, _, _, _),
throw(error(existence_error(category, CtgOrPtc), logtalk(_, _)))
; '$lgt_extends_category_'(_, CtgOrPtc, _), \+ '$lgt_current_category_'(CtgOrPtc, _, _, _, _, _),
throw(error(existence_error(category, CtgOrPtc), logtalk(_, _)))
).
'$lgt_runtime_normalized_error_handler'(error(existence_error(procedure, TFunctor/TArity), logtalk(Goal, ExCtx))) :-
'$lgt_decompile_predicate_indicators'(TFunctor/TArity, _, _, Functor/Arity),
throw(error(existence_error(procedure, Functor/Arity), logtalk(Goal, ExCtx))).
'$lgt_runtime_normalized_error_handler'(error(existence_error(procedure, TFunctor/TArity), _)) :-
'$lgt_decompile_predicate_indicators'(TFunctor/TArity, _, _, Functor/Arity),
throw(error(existence_error(procedure, Functor/Arity), logtalk(_, _))).
'$lgt_runtime_normalized_error_handler'(Error) :-
throw(Error).
'$lgt_runtime_thread_error_handler_helper'(logtalk(threaded_exit(TGoal),ExCtx), logtalk(threaded_exit(Goal),ExCtx)) :-
!,
'$lgt_runtime_thread_error_tgoal_goal'(TGoal, Goal).
'$lgt_runtime_thread_error_handler_helper'(logtalk(threaded_exit(TGoal,Tag),ExCtx), logtalk(threaded_exit(Goal,Tag),ExCtx)) :-
!,
'$lgt_runtime_thread_error_tgoal_goal'(TGoal, Goal).
'$lgt_runtime_thread_error_handler_helper'(Context, Context).
'$lgt_runtime_thread_error_tgoal_goal'('$lgt_send_to_obj_ne_nv'(Self,Goal0,_), Goal) :-
!,
( Self == user ->
Goal = Goal0
; Goal = Self::Goal0
).
'$lgt_runtime_thread_error_tgoal_goal'('$lgt_send_to_obj_nv'(Self,Goal0,_), Goal) :-
!,
( Self == user ->
Goal = Goal0
; Goal = Self::Goal0
).
'$lgt_runtime_thread_error_tgoal_goal'(TGoal, Goal) :-
functor(TGoal, TFunctor, TArity),
'$lgt_decompile_predicate_indicators'(TFunctor/TArity, _, _, Functor/Arity),
functor(Goal, Functor, Arity),
'$lgt_unify_head_thead_arguments'(Goal, TGoal, _).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% built-in predicates
%
% in general, two main clauses are provided: one for calls in "user", e.g.
% calls at the top-level, and one for compiled calls
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% current_object(?object_identifier)
current_object(Obj) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_object'(Obj, ExCtx).
'$lgt_current_object'(Obj, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Obj, logtalk(current_object(Obj), ExCtx)),
'$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _).
% current_protocol(?protocol_identifier)
current_protocol(Ptc) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_protocol'(Ptc, ExCtx).
'$lgt_current_protocol'(Ptc, ExCtx) :-
'$lgt_check'(var_or_protocol_identifier, Ptc, logtalk(current_protocol(Ptc), ExCtx)),
'$lgt_current_protocol_'(Ptc, _, _, _, _).
% current_category(?category_identifier)
current_category(Ctg) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_category'(Ctg, ExCtx).
'$lgt_current_category'(Ctg, ExCtx) :-
'$lgt_check'(var_or_category_identifier, Ctg, logtalk(current_category(Ctg), ExCtx)),
'$lgt_current_category_'(Ctg, _, _, _, _, _).
% object_property(?object_identifier, ?object_property)
%
% the implementation ensures that no spurious choice-points are
% created when the predicate is called with a bound property argument
object_property(Obj, Prop) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_object_property'(Obj, Prop, ExCtx).
'$lgt_object_property'(Obj, Prop, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Obj, logtalk(object_property(Obj, Prop), ExCtx)),
'$lgt_check'(var_or_object_property, Prop, logtalk(object_property(Obj, Prop), ExCtx)),
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, DDcl, DDef, Rnm, Flags),
'$lgt_object_property'(Prop, Obj, Dcl, Def, DDcl, DDef, Rnm, Flags).
'$lgt_object_property'(module, _, _, _, _, _, _, Flags) :-
Flags /\ 1024 =:= 1024.
'$lgt_object_property'(debugging, _, _, _, _, _, _, Flags) :-
Flags /\ 512 =:= 512.
'$lgt_object_property'(context_switching_calls, _, _, _, _, _, _, Flags) :-
Flags /\ 256 =:= 256.
'$lgt_object_property'(dynamic_declarations, _, _, _, _, _, _, Flags) :-
Flags /\ 128 =:= 128.
'$lgt_object_property'(complements(Complements), _, _, _, _, _, _, Flags) :-
( Flags /\ 64 =:= 64 ->
Complements = allow
; Flags /\ 32 =:= 32,
Complements = restrict
).
'$lgt_object_property'(complements, _, _, _, _, _, _, Flags) :-
% deprecated Logtalk 2.x object property
( Flags /\ 64 =:= 64 ->
true
; Flags /\ 32 =:= 32
).
'$lgt_object_property'(events, Obj, _, _, _, _, _, Flags) :-
( Obj == user ->
% depends on the current default value of the flag
'$lgt_current_flag_'(events, allow)
; % fixed value (at compilation time) for all other objects
Flags /\ 16 =:= 16
).
'$lgt_object_property'(source_data, _, _, _, _, _, _, Flags) :-
Flags /\ 8 =:= 8.
'$lgt_object_property'(threaded, _, _, _, _, _, _, Flags) :-
Flags /\ 4 =:= 4.
'$lgt_object_property'((dynamic), _, _, _, _, _, _, Flags) :-
Flags /\ 2 =:= 2.
'$lgt_object_property'(static, _, _, _, _, _, _, Flags) :-
Flags /\ 2 =:= 0.
'$lgt_object_property'(built_in, _, _, _, _, _, _, Flags) :-
Flags /\ 1 =:= 1.
'$lgt_object_property'(file(Path), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, file_lines(Basename, Directory, _, _)) ->
atom_concat(Directory, Basename, Path)
; fail
).
'$lgt_object_property'(file(Basename, Directory), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, file_lines(Basename, Directory, _, _)) ->
true
; fail
).
'$lgt_object_property'(lines(Start, End), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, file_lines(_, _, Start, End)) ->
true
; fail
).
'$lgt_object_property'(directive(Start, End), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, directive(Start, End)) ->
true
; fail
).
'$lgt_object_property'(info(Info), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, info(Info)) ->
true
; fail
).
'$lgt_object_property'(public(Resources), Obj, Dcl, _, DDcl, _, _, Flags) :-
'$lgt_object_property_resources'(Obj, Dcl, DDcl, Flags, p(p(p)), Resources).
'$lgt_object_property'(protected(Resources), Obj, Dcl, _, DDcl, _, _, Flags) :-
'$lgt_object_property_resources'(Obj, Dcl, DDcl, Flags, p(p), Resources).
'$lgt_object_property'(private(Resources), Obj, Dcl, _, DDcl, _, _, Flags) :-
'$lgt_object_property_resources'(Obj, Dcl, DDcl, Flags, p, Resources).
'$lgt_object_property'(declares(Predicate, Properties), Obj, Dcl, _, DDcl, _, _, Flags) :-
'$lgt_object_property_declares'(Obj, Dcl, DDcl, Flags, Predicate, Properties).
'$lgt_object_property'(defines(Predicate, Properties), Obj, _, Def, _, DDef, _, Flags) :-
'$lgt_object_property_defines'(Obj, Def, DDef, Predicate, Flags, Properties).
'$lgt_object_property'(includes(Predicate, From, Properties), Obj, _, _, _, _, _, _) :-
'$lgt_entity_property_includes'(Obj, Predicate, From, Properties).
'$lgt_object_property'(provides(Predicate, To, Properties), Obj, _, _, _, _, _, _) :-
'$lgt_entity_property_provides'(Obj, Predicate, To, Properties).
'$lgt_object_property'(alias(Alias, Properties), Obj, _, _, _, _, _, _) :-
'$lgt_entity_property_alias'(Obj, Alias, Properties).
'$lgt_object_property'(calls(Predicate, Properties), Obj, _, _, _, _, _, _) :-
'$lgt_entity_property_calls'(Obj, Predicate, Properties).
'$lgt_object_property'(updates(Predicate, Properties), Obj, _, _, _, _, _, _) :-
'$lgt_entity_property_updates'(Obj, Predicate, Properties).
'$lgt_object_property'(number_of_clauses(Total), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, number_of_clauses(Total, _)) ->
true
; fail
).
'$lgt_object_property'(number_of_rules(Total), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, number_of_rules(Total, _)) ->
true
; fail
).
'$lgt_object_property'(number_of_user_clauses(TotalUser), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, number_of_clauses(_, TotalUser)) ->
true
; fail
).
'$lgt_object_property'(number_of_user_rules(TotalUser), Obj, _, _, _, _, _, _) :-
( '$lgt_entity_property_'(Obj, number_of_rules(_, TotalUser)) ->
true
; fail
).
'$lgt_object_property_resources'(Obj, Dcl, DDcl, Flags, Scope, Resources) :-
% the caller uses this predicate to group object resources by scope
findall(
Resource,
'$lgt_object_property_resource'(Obj, Dcl, DDcl, Flags, Scope, Resource),
Resources
).
'$lgt_object_property_resource'(_, Dcl, _, _, Scope, Functor/Arity) :-
call(Dcl, Predicate, Scope, _, _),
functor(Predicate, Functor, Arity).
'$lgt_object_property_resource'(_, _, DDcl, Flags, Scope, Functor/Arity) :-
Flags /\ 128 =:= 128,
% dynamic predicate declarations are allowed
call(DDcl, Predicate, Scope),
functor(Predicate, Functor, Arity).
'$lgt_object_property_resource'(Obj, _, _, _, Scope, op(Priority, Specifier, Operator)) :-
'$lgt_entity_property_'(Obj, op(Priority, Specifier, Operator, Scope)).
% category_property(?category_identifier, ?category_property)
%
% the implementation ensures that no spurious choice-points are
% created when the predicate is called with a bound property argument
category_property(Ctg, Prop) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_category_property'(Ctg, Prop, ExCtx).
'$lgt_category_property'(Ctg, Prop, ExCtx) :-
'$lgt_check'(var_or_category_identifier, Ctg, logtalk(category_property(Ctg, Prop), ExCtx)),
'$lgt_check'(var_or_category_property, Prop, logtalk(category_property(Ctg, Prop), ExCtx)),
'$lgt_current_category_'(Ctg, _, Dcl, Def, Rnm, Flags),
'$lgt_category_property'(Prop, Ctg, Dcl, Def, Rnm, Flags).
'$lgt_category_property'(debugging, _, _, _, _, Flags) :-
Flags /\ 512 =:= 512.
'$lgt_category_property'(events, _, _, _, _, Flags) :-
Flags /\ 16 =:= 16.
'$lgt_category_property'(source_data, _, _, _, _, Flags) :-
Flags /\ 8 =:= 8.
'$lgt_category_property'((dynamic), _, _, _, _, Flags) :-
Flags /\ 2 =:= 2.
'$lgt_category_property'(static, _, _, _, _, Flags) :-
Flags /\ 2 =:= 0.
'$lgt_category_property'(built_in, _, _, _, _, Flags) :-
Flags /\ 1 =:= 1.
'$lgt_category_property'(file(Path), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, file_lines(Basename, Directory, _, _)) ->
atom_concat(Directory, Basename, Path)
; fail
).
'$lgt_category_property'(file(Basename, Directory), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, file_lines(Basename, Directory, _, _)) ->
true
; fail
).
'$lgt_category_property'(lines(Start, End), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, file_lines(_, _, Start, End)) ->
true
; fail
).
'$lgt_category_property'(directive(Start, End), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, directive(Start, End)) ->
true
; fail
).
'$lgt_category_property'(info(Info), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, info(Info)) ->
true
; fail
).
'$lgt_category_property'(public(Resources), Ctg, Dcl, _, _, Flags) :-
'$lgt_category_property_resources'(Ctg, Dcl, Flags, p(p(p)), Resources).
'$lgt_category_property'(protected(Resources), Ctg, Dcl, _, _, Flags) :-
'$lgt_category_property_resources'(Ctg, Dcl, Flags, p(p), Resources).
'$lgt_category_property'(private(Resources), Ctg, Dcl, _, _, Flags) :-
'$lgt_category_property_resources'(Ctg, Dcl, Flags, p, Resources).
'$lgt_category_property'(declares(Predicate, Properties), Ctg, Dcl, _, _, _) :-
'$lgt_category_property_declares'(Ctg, Dcl, Predicate, Properties).
'$lgt_category_property'(defines(Predicate, Properties), Ctg, _, Def, _, Flags) :-
'$lgt_category_property_defines'(Ctg, Def, Predicate, Flags, Properties).
'$lgt_category_property'(includes(Predicate, From, Properties), Ctg, _, _, _, _) :-
'$lgt_entity_property_includes'(Ctg, Predicate, From, Properties).
'$lgt_category_property'(provides(Predicate, To, Properties), Ctg, _, _, _, _) :-
'$lgt_entity_property_provides'(Ctg, Predicate, To, Properties).
'$lgt_category_property'(calls(Predicate, Properties), Ctg, _, _, _, _) :-
'$lgt_entity_property_calls'(Ctg, Predicate, Properties).
'$lgt_category_property'(updates(Predicate, Properties), Ctg, _, _, _, _) :-
'$lgt_entity_property_updates'(Ctg, Predicate, Properties).
'$lgt_category_property'(alias(Alias, Properties), Ctg, _, _, _, _) :-
'$lgt_entity_property_alias'(Ctg, Alias, Properties).
'$lgt_category_property'(number_of_clauses(Total), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, number_of_clauses(Total, _)) ->
true
; fail
).
'$lgt_category_property'(number_of_rules(Total), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, number_of_rules(Total, _)) ->
true
; fail
).
'$lgt_category_property'(number_of_user_clauses(TotalUser), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, number_of_clauses(_, TotalUser)) ->
true
; fail
).
'$lgt_category_property'(number_of_user_rules(TotalUser), Ctg, _, _, _, _) :-
( '$lgt_entity_property_'(Ctg, number_of_rules(_, TotalUser)) ->
true
; fail
).
'$lgt_category_property_resources'(Ctg, Dcl, Flags, Scope, Resources) :-
% the caller uses this predicate to group object resources by scope
findall(
Resource,
'$lgt_category_property_resource'(Ctg, Dcl, Flags, Scope, Resource),
Resources
).
'$lgt_category_property_resource'(Ctg, Dcl, _, Scope, Functor/Arity) :-
call(Dcl, Predicate, Scope, _, _, Ctg),
functor(Predicate, Functor, Arity).
'$lgt_category_property_resource'(Ctg, _, _, Scope, op(Priority, Specifier, Operator)) :-
'$lgt_entity_property_'(Ctg, op(Priority, Specifier, Operator, Scope)).
% protocol_property(?protocol_identifier, ?protocol_property)
%
% the implementation ensures that no spurious choice-points are
% created when the predicate is called with a bound property argument
protocol_property(Ptc, Prop) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_protocol_property'(Ptc, Prop, ExCtx).
'$lgt_protocol_property'(Ptc, Prop, ExCtx) :-
'$lgt_check'(var_or_protocol_identifier, Ptc, logtalk(protocol_property(Ptc, Prop), ExCtx)),
'$lgt_check'(var_or_protocol_property, Prop, logtalk(protocol_property(Ptc, Prop), ExCtx)),
'$lgt_current_protocol_'(Ptc, _, Dcl, Rnm, Flags),
'$lgt_protocol_property'(Prop, Ptc, Dcl, Rnm, Flags).
'$lgt_protocol_property'(debugging, _, _, _, Flags) :-
Flags /\ 512 =:= 512.
'$lgt_protocol_property'(source_data, _, _, _, Flags) :-
Flags /\ 8 =:= 8.
'$lgt_protocol_property'((dynamic), _, _, _, Flags) :-
Flags /\ 2 =:= 2.
'$lgt_protocol_property'(static, _, _, _, Flags) :-
Flags /\ 2 =:= 0.
'$lgt_protocol_property'(built_in, _, _, _, Flags) :-
Flags /\ 1 =:= 1.
'$lgt_protocol_property'(file(Path), Ptc, _, _, _) :-
( '$lgt_entity_property_'(Ptc, file_lines(Basename, Directory, _, _)) ->
atom_concat(Directory, Basename, Path)
; fail
).
'$lgt_protocol_property'(file(Basename, Directory), Ptc, _, _, _) :-
( '$lgt_entity_property_'(Ptc, file_lines(Basename, Directory, _, _)) ->
true
; fail
).
'$lgt_protocol_property'(lines(Start, End), Ptc, _, _, _) :-
( '$lgt_entity_property_'(Ptc, file_lines(_, _, Start, End)) ->
true
; fail
).
'$lgt_protocol_property'(directive(Start, End), Ptc, _, _, _) :-
( '$lgt_entity_property_'(Ptc, directive(Start, End)) ->
true
; fail
).
'$lgt_protocol_property'(info(Info), Ptc, _, _, _) :-
( '$lgt_entity_property_'(Ptc, info(Info)) ->
true
; fail
).
'$lgt_protocol_property'(public(Resources), Ptc, Dcl, _, Flags) :-
'$lgt_protocol_property_resources'(Ptc, Dcl, Flags, p(p(p)), Resources).
'$lgt_protocol_property'(protected(Resources), Ptc, Dcl, _, Flags) :-
'$lgt_protocol_property_resources'(Ptc, Dcl, Flags, p(p), Resources).
'$lgt_protocol_property'(private(Resources), Ptc, Dcl, _, Flags) :-
'$lgt_protocol_property_resources'(Ptc, Dcl, Flags, p, Resources).
'$lgt_protocol_property'(declares(Predicate, Properties), Ptc, Dcl, _, _) :-
'$lgt_protocol_property_declares'(Ptc, Dcl, Predicate, Properties).
'$lgt_protocol_property'(alias(Alias, Properties), Ptc, _, _, _) :-
'$lgt_entity_property_alias'(Ptc, Alias, Properties).
'$lgt_protocol_property_resources'(Ptc, Dcl, Flags, Scope, Resources) :-
% the caller uses this predicate to group object resources by scope
findall(
Resource,
'$lgt_protocol_property_resource'(Ptc, Dcl, Flags, Scope, Resource),
Resources
).
'$lgt_protocol_property_resource'(Ptc, Dcl, _, Scope, Functor/Arity) :-
call(Dcl, Predicate, Scope, _, _, Ptc),
functor(Predicate, Functor, Arity).
'$lgt_protocol_property_resource'(Ptc, _, _, Scope, op(Priority, Specifier, Operator)) :-
'$lgt_entity_property_'(Ptc, op(Priority, Specifier, Operator, Scope)).
'$lgt_object_property_declares'(Obj, Dcl, DDcl, EntityFlags, Functor/Arity, Properties) :-
( call(Dcl, Predicate, Scope, Meta, Flags)
; EntityFlags /\ 128 =:= 128,
% dynamic predicate declarations are allowed
call(DDcl, Predicate, Scope),
Meta = no,
Flags = 2
),
functor(Predicate, Functor, Arity),
'$lgt_scope'(ScopeAsAtom, Scope),
'$lgt_entity_property_declares'(Obj, Functor/Arity, ScopeAsAtom, Meta, Flags, Properties).
'$lgt_category_property_declares'(Ctg, Dcl, Functor/Arity, Properties) :-
call(Dcl, Predicate, Scope, Meta, Flags, Ctg),
functor(Predicate, Functor, Arity),
'$lgt_scope'(ScopeAsAtom, Scope),
'$lgt_entity_property_declares'(Ctg, Functor/Arity, ScopeAsAtom, Meta, Flags, Properties).
'$lgt_protocol_property_declares'(Ptc, Dcl, Functor/Arity, Properties) :-
call(Dcl, Predicate, Scope, Meta, Flags, Ptc),
functor(Predicate, Functor, Arity),
'$lgt_scope'(ScopeAsAtom, Scope),
'$lgt_entity_property_declares'(Ptc, Functor/Arity, ScopeAsAtom, Meta, Flags, Properties).
'$lgt_entity_property_declares'(Entity, Functor/Arity, Scope, Meta, Flags, Properties) :-
( '$lgt_predicate_property_'(Entity, Functor/Arity, info(Info)) ->
Properties0 = [info(Info)]
; Properties0 = []
),
findall(mode(Mode, Solutions), '$lgt_predicate_property_'(Entity, Functor/Arity, mode(Mode, Solutions)), Modes),
'$lgt_append'(Modes, Properties0, Properties1),
( '$lgt_predicate_property_'(Entity, Functor/Arity, declaration_location(Location)) ->
( Location = include(File, BeginLine-EndLine) ->
Properties2 = [include(File), lines(BeginLine,EndLine), line_count(BeginLine)| Properties1]
; Location = BeginLine-EndLine,
Properties2 = [lines(BeginLine,EndLine), line_count(BeginLine)| Properties1]
)
; Properties2 = Properties1
),
( %Flags /\ 64 =:= 64,
Meta == no ->
Properties7 = Properties6
; Properties7 = [meta_predicate(Meta)| Properties6]
),
( Flags /\ 32 =:= 32,
'$lgt_predicate_property_'(Entity, Functor/Arity, coinductive(Template)) ->
Properties3 = [coinductive(Template)| Properties2]
; Properties3 = Properties2
),
( Flags /\ 16 =:= 16 ->
Properties4 = [(multifile)| Properties3]
; Properties4 = Properties3
),
( Flags /\ 8 =:= 8 ->
Arity2 is Arity - 2,
Properties5 = [non_terminal(Functor//Arity2)| Properties4]
; Properties5 = Properties4
),
( Flags /\ 4 =:= 4 ->
Properties6 = [synchronized| Properties5]
; Properties6 = Properties5
),
( Flags /\ 2 =:= 2 ->
Properties = [Scope, scope(Scope), (dynamic)| Properties7]
; Properties = [Scope, scope(Scope), static| Properties7]
).
'$lgt_object_property_defines'(Obj, Def, DDef, Functor/Arity, Flags, Properties) :-
( call(Def, Predicate, _, _)
; call(DDef, Predicate, _, _)
),
functor(Predicate, Functor, Arity),
'$lgt_entity_property_defines'(Obj, Functor/Arity, Flags, Properties).
'$lgt_category_property_defines'(Ctg, Def, Functor/Arity, Flags, Properties) :-
call(Def, Predicate, _, _, Ctg),
functor(Predicate, Functor, Arity),
'$lgt_entity_property_defines'(Ctg, Functor/Arity, Flags, Properties).
'$lgt_entity_property_defines'(Entity, Functor/Arity, _, Properties) :-
'$lgt_predicate_property_'(Entity, Functor/Arity, flags_clauses_rules_location(Flags, Clauses, Rules, Location)),
!,
( Location = include(File, BeginLine-EndLine) ->
Properties0 = [include(File), lines(BeginLine,EndLine), line_count(BeginLine), number_of_clauses(Clauses), number_of_rules(Rules)]
; Location == 0-0 ->
% auxiliary predicate
Properties0 = [number_of_clauses(Clauses), number_of_rules(Rules)]
; Location = BeginLine-EndLine,
Properties0 = [lines(BeginLine,EndLine), line_count(BeginLine), number_of_clauses(Clauses), number_of_rules(Rules)]
),
( Flags /\ 8 =:= 8 ->
Properties1 = [recursive| Properties0]
; Properties1 = Properties0
),
( Flags /\ 4 =:= 4 ->
Properties2 = [inline| Properties1]
; Properties2 = Properties1
),
( Flags /\ 2 =:= 2 ->
Arity2 is Arity - 2,
Properties3 = [non_terminal(Functor//Arity2)| Properties2]
; Properties3 = Properties2
),
( Flags /\ 1 =:= 1 ->
Properties = [auxiliary| Properties3]
; Properties = Properties3
).
% likely a dynamic or a multifile predicate with no local clauses
'$lgt_entity_property_defines'(_, _, Flags, [number_of_clauses(0), number_of_rules(0)]) :-
Flags /\ 2 =:= 0,
% static entity
!.
% dynamically created entity
'$lgt_entity_property_defines'(_, _, _, []).
'$lgt_entity_property_includes'(Entity, Functor/Arity, From, Properties) :-
'$lgt_predicate_property_'(From, Functor/Arity, clauses_rules_location_to(Clauses, Rules, Location, Entity)),
( Location = include(File, BeginLine-EndLine) ->
LocationProperties = [include(File), lines(BeginLine,EndLine), line_count(BeginLine)]
; Location = BeginLine-EndLine,
LocationProperties = [lines(BeginLine,EndLine), line_count(BeginLine)]
),
Properties = [number_of_clauses(Clauses), number_of_rules(Rules)| LocationProperties].
'$lgt_entity_property_provides'(Entity, Functor/Arity, To, Properties) :-
'$lgt_predicate_property_'(Entity, Functor/Arity, clauses_rules_location_to(Clauses, Rules, Location, To)),
( Location = include(File, BeginLine-EndLine) ->
LocationProperties = [include(File), lines(BeginLine,EndLine), line_count(BeginLine)]
; Location = BeginLine-EndLine,
LocationProperties = [lines(BeginLine,EndLine), line_count(BeginLine)]
),
Properties = [number_of_clauses(Clauses), number_of_rules(Rules)| LocationProperties].
'$lgt_entity_property_alias'(Entity, Alias, Properties) :-
'$lgt_entity_property_'(Entity, object_alias(Original, Alias, Location)),
( Location = include(File, BeginLine-EndLine) ->
Properties = [object, for(Original), include(File), lines(BeginLine,EndLine), line_count(BeginLine)]
; Location = BeginLine-EndLine,
Properties = [object, for(Original), lines(BeginLine,EndLine), line_count(BeginLine)]
).
'$lgt_entity_property_alias'(Entity, Alias, Properties) :-
'$lgt_entity_property_'(Entity, module_alias(Original, Alias, Location)),
( Location = include(File, BeginLine-EndLine) ->
Properties = [module, for(Original), include(File), lines(BeginLine,EndLine), line_count(BeginLine)]
; Location = BeginLine-EndLine,
Properties = [module, for(Original), lines(BeginLine,EndLine), line_count(BeginLine)]
).
'$lgt_entity_property_alias'(Entity, AliasFunctor/Arity, Properties) :-
'$lgt_entity_property_'(Entity, predicate_alias(From, OriginalFunctor/Arity, AliasFunctor/Arity, NonTerminalFlag, Location)),
( Location = include(File, BeginLine-EndLine) ->
LocationProperties = [include(File), lines(BeginLine,EndLine), line_count(BeginLine)]
; Location = BeginLine-EndLine,
LocationProperties = [lines(BeginLine,EndLine), line_count(BeginLine)]
),
( NonTerminalFlag =:= 1 ->
Arity2 is Arity - 2,
Properties = [predicate, for(OriginalFunctor/Arity), from(From), non_terminal(AliasFunctor//Arity2)| LocationProperties]
; Properties = [predicate, for(OriginalFunctor/Arity), from(From)| LocationProperties]
).
'$lgt_entity_property_calls'(Entity, Call, Properties) :-
'$lgt_entity_property_'(Entity, calls(Call, Caller, Alias, NonTerminal, Location)),
( NonTerminal == no ->
NonTerminalProperty = []
; NonTerminalProperty = [non_terminal(NonTerminal)]
),
( Location = include(File, BeginLine-EndLine) ->
LocationProperties = [include(File), lines(BeginLine,EndLine), line_count(BeginLine)| NonTerminalProperty]
; Location = BeginLine-EndLine,
LocationProperties = [lines(BeginLine,EndLine), line_count(BeginLine)| NonTerminalProperty]
),
( Alias == no ->
OtherProperties = LocationProperties
; OtherProperties = [alias(Alias)| LocationProperties]
),
Properties = [caller(Caller)| OtherProperties].
'$lgt_entity_property_updates'(Entity, Predicate, Properties) :-
'$lgt_entity_property_'(Entity, updates(Predicate, Updater, Alias, NonTerminal, Location)),
( NonTerminal == no ->
NonTerminalProperty = []
; NonTerminalProperty = [non_terminal(NonTerminal)]
),
( Location = include(File, BeginLine-EndLine) ->
LocationProperties = [include(File), lines(BeginLine,EndLine), line_count(BeginLine)| NonTerminalProperty]
; Location = BeginLine-EndLine,
LocationProperties = [lines(BeginLine,EndLine), line_count(BeginLine)| NonTerminalProperty]
),
( Alias == no ->
OtherProperties = LocationProperties
; OtherProperties = [alias(Alias)| LocationProperties]
),
Properties = [updater(Updater)| OtherProperties].
% create_object(?object_identifier, +list, +list, +list)
create_object(Obj, Relations, Directives, Clauses) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_create_object'(Obj, Relations, Directives, Clauses, ExCtx).
'$lgt_create_object'(Obj, Relations, Directives, Clauses, ExCtx) :-
nonvar(Obj),
( \+ callable(Obj),
throw(error(type_error(object_identifier, Obj), logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)))
; '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _),
throw(error(permission_error(modify, object, Obj), logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)))
; '$lgt_current_category_'(Obj, _, _, _, _, _),
throw(error(permission_error(modify, category, Obj), logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)))
; '$lgt_current_protocol_'(Obj, _, _, _, _),
throw(error(permission_error(modify, protocol, Obj), logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)))
; functor(Obj, '{}', 1),
throw(error(permission_error(create, object, Obj), logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)))
).
'$lgt_create_object'(Obj, Relations, Directives, Clauses, ExCtx) :-
'$lgt_check'(list, Relations, logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)),
'$lgt_check'(list, Directives, logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)),
'$lgt_check'(list, Clauses, logtalk(create_object(Obj, Relations, Directives, Clauses), ExCtx)),
catch(
'$lgt_create_object_checked'(Obj, Relations, Directives, Clauses),
Error,
'$lgt_create_entity_error_handler'(Error, create_object(Obj, Relations, Directives, Clauses), ExCtx)
).
'$lgt_create_object_checked'(Obj, Relations, Directives, Clauses) :-
( var(Obj) ->
'$lgt_generate_entity_identifier'(object, Obj)
; true
),
% set the initial compilation context for compiling the object directives and clauses
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, runtime, _, '-'(-1, -1), _),
% we need to compile the object relations first as we need to know if we are compiling
% a prototype or an instance/class when compiling the object identifier as the generated
% internal functors are different for each case
'$lgt_compile_object_relations'(Relations, Obj, Ctx),
'$lgt_compile_object_identifier'(Obj, Ctx),
assertz('$lgt_pp_dynamic_'),
'$lgt_compile_logtalk_directives'(Directives, Ctx),
% the list of clauses may also include grammar rules
'$lgt_compile_runtime_terms'(Clauses),
'$lgt_generate_def_table_clauses'(Ctx),
'$lgt_compile_predicate_calls'(runtime),
'$lgt_generate_object_clauses',
'$lgt_generate_object_directives',
'$lgt_assert_dynamic_entity'(object),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_cc_clauses',
'$lgt_clean_pp_object_clauses',
'$lgt_clean_pp_runtime_clauses'.
% create_category(?category_identifier, +list, +list, +list)
create_category(Ctg, Relations, Directives, Clauses) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_create_category'(Ctg, Relations, Directives, Clauses, ExCtx).
'$lgt_create_category'(Ctg, Relations, Directives, Clauses, ExCtx) :-
nonvar(Ctg),
( \+ callable(Ctg),
throw(error(type_error(category_identifier, Ctg), logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)))
; '$lgt_current_category_'(Ctg, _, _, _, _, _),
throw(error(permission_error(modify, category, Ctg), logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)))
; '$lgt_current_object_'(Ctg, _, _, _, _, _, _, _, _, _, _),
throw(error(permission_error(modify, object, Ctg), logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)))
; '$lgt_current_protocol_'(Ctg, _, _, _, _),
throw(error(permission_error(modify, protocol, Ctg), logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)))
).
'$lgt_create_category'(Ctg, Relations, Directives, Clauses, ExCtx) :-
'$lgt_check'(list, Relations, logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)),
'$lgt_check'(list, Directives, logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)),
'$lgt_check'(list, Clauses, logtalk(create_category(Ctg, Relations, Directives, Clauses), ExCtx)),
catch(
'$lgt_create_category_checked'(Ctg, Relations, Directives, Clauses),
Error,
'$lgt_create_entity_error_handler'(Error, create_category(Ctg, Relations, Directives, Clauses), ExCtx)
).
'$lgt_create_category_checked'(Ctg, Relations, Directives, Clauses) :-
( var(Ctg) ->
'$lgt_generate_entity_identifier'(category, Ctg)
; true
),
% set the initial compilation context for compiling the category directives and clauses
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, runtime, _, '-'(-1, -1), _),
'$lgt_compile_category_identifier'(Ctg, Ctx),
'$lgt_compile_category_relations'(Relations, Ctg, Ctx),
assertz('$lgt_pp_dynamic_'),
'$lgt_compile_logtalk_directives'(Directives, Ctx),
% the list of clauses may also include grammar rules
'$lgt_compile_runtime_terms'(Clauses),
'$lgt_generate_def_table_clauses'(Ctx),
'$lgt_compile_predicate_calls'(runtime),
'$lgt_generate_category_clauses',
'$lgt_generate_category_directives',
'$lgt_assert_dynamic_entity'(category),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_cc_clauses',
'$lgt_clean_pp_category_clauses',
'$lgt_clean_pp_runtime_clauses',
% complementing categories can invalidate dynamic binding cache entries
( '$lgt_member'(Relation, Relations),
functor(Relation, complements, _) ->
'$lgt_clean_lookup_caches'
; true
).
% create_protocol(?protocol_identifier, +list, +list)
create_protocol(Ptc, Relations, Directives) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_create_protocol'(Ptc, Relations, Directives, ExCtx).
'$lgt_create_protocol'(Ptc, Relations, Directives, ExCtx) :-
nonvar(Ptc),
( \+ atom(Ptc),
throw(error(type_error(protocol_identifier, Ptc), logtalk(create_protocol(Ptc, Relations, Directives), ExCtx)))
; '$lgt_current_protocol_'(Ptc, _, _, _, _),
throw(error(permission_error(modify, protocol, Ptc), logtalk(create_protocol(Ptc, Relations, Directives), ExCtx)))
; '$lgt_current_object_'(Ptc, _, _, _, _, _, _, _, _, _, _),
throw(error(permission_error(modify, object, Ptc), logtalk(create_protocol(Ptc, Relations, Directives), ExCtx)))
; '$lgt_current_category_'(Ptc, _, _, _, _, _),
throw(error(permission_error(modify, category, Ptc), logtalk(create_protocol(Ptc, Relations, Directives), ExCtx)))
).
'$lgt_create_protocol'(Ptc, Relations, Directives, ExCtx) :-
'$lgt_check'(list, Relations, logtalk(create_protocol(Ptc, Relations, Directives), ExCtx)),
'$lgt_check'(list, Directives, logtalk(create_protocol(Ptc, Relations, Directives), ExCtx)),
catch(
'$lgt_create_protocol_checked'(Ptc, Relations, Directives),
Error,
'$lgt_create_entity_error_handler'(Error, create_protocol(Ptc, Relations, Directives), ExCtx)
).
'$lgt_create_protocol_checked'(Ptc, Relations, Directives) :-
( var(Ptc) ->
'$lgt_generate_entity_identifier'(protocol, Ptc)
; true
),
% set the initial compilation context for compiling the protocol directives
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, runtime, _, '-'(-1, -1), _),
'$lgt_compile_protocol_identifier'(Ptc, Ctx),
'$lgt_compile_protocol_relations'(Relations, Ptc, Ctx),
assertz('$lgt_pp_dynamic_'),
'$lgt_compile_logtalk_directives'(Directives, Ctx),
'$lgt_generate_protocol_clauses',
'$lgt_generate_protocol_directives',
'$lgt_assert_dynamic_entity'(protocol),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_cc_clauses',
'$lgt_clean_pp_protocol_clauses',
'$lgt_clean_pp_runtime_clauses'.
% '$lgt_generate_entity_identifier'(+atom, -entity_identifier)
%
% generates a new, unique, entity identifier by appending an integer to a base char
%
% note that it's possible to run out of (generated) entity identifiers when using a
% backend Prolog compiler with bounded integer support
'$lgt_generate_entity_identifier'(Kind, Identifier) :-
retract('$lgt_dynamic_entity_counter_'(Kind, Base, Count)),
char_code(Base, Code),
repeat,
'$lgt_next_integer'(Count, New),
number_codes(New, Codes),
atom_codes(Identifier, [Code| Codes]),
% objects, protocols, and categories share a single namespace and there's
% no guarantee that a user named entity will not clash with the generated
% identifier despite the use of a per entity type base character
\+ '$lgt_current_protocol_'(Identifier, _, _, _, _),
\+ '$lgt_current_object_'(Identifier, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_current_category_'(Identifier, _, _, _, _, _),
asserta('$lgt_dynamic_entity_counter_'(Kind, Base, New)),
!.
'$lgt_next_integer'(I, I).
'$lgt_next_integer'(I, K) :-
J is I + 1,
'$lgt_next_integer'(J, K).
% '$lgt_create_entity_error_handler'(@nonvar, @callable, @execution_context)
%
% error handler for the dynamic entity creation built-in predicates;
% handles both compiler first stage and second stage errors
'$lgt_create_entity_error_handler'(error(Error,_), Goal, ExCtx) :-
!,
% compiler second stage error; unwrap the error
'$lgt_create_entity_error_handler'(Error, Goal, ExCtx).
'$lgt_create_entity_error_handler'(Error, Goal, ExCtx) :-
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
throw(error(Error, logtalk(Goal, ExCtx))).
% abolish_object(+object_identifier)
abolish_object(Obj) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_abolish_object'(Obj, ExCtx).
'$lgt_abolish_object'(Obj, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(abolish_object(Obj), ExCtx)),
'$lgt_abolish_object_checked'(Obj, ExCtx).
'$lgt_abolish_object_checked'(Obj, ExCtx) :-
( '$lgt_current_object_'(Obj, _, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, Flags) ->
( Flags /\ 2 =:= 2 ->
% dynamic object
'$lgt_abolish_entity_predicates'(Def),
'$lgt_abolish_entity_predicates'(DDef),
abolish(Dcl/4),
abolish(Dcl/6),
abolish(Def/3),
abolish(Def/5),
abolish(Super/5),
abolish(IDcl/6),
abolish(IDef/5),
abolish(DDcl/2),
abolish(DDef/3),
abolish(Rnm/3),
retractall('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _)),
retractall('$lgt_entity_property_'(Obj, _)),
retractall('$lgt_predicate_property_'(Obj, _, _)),
retractall('$lgt_extends_object_'(Obj, _, _)),
retractall('$lgt_instantiates_class_'(Obj, _, _)),
retractall('$lgt_specializes_class_'(Obj, _, _)),
retractall('$lgt_implements_protocol_'(Obj, _, _)),
retractall('$lgt_imports_category_'(Obj, _, _)),
forall(
'$lgt_current_engine_'(Obj, Engine, _, _),
'$lgt_threaded_engine_destroy'(Engine, ExCtx)
),
'$lgt_clean_lookup_caches'
; throw(error(permission_error(modify, static_object, Obj), logtalk(abolish_object(Obj), ExCtx)))
)
; throw(error(existence_error(object, Obj), logtalk(abolish_object(Obj), ExCtx)))
).
% abolish_category(+category_identifier)
abolish_category(Ctg) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_abolish_category'(Ctg, ExCtx).
'$lgt_abolish_category'(Ctg, ExCtx) :-
'$lgt_check'(category_identifier, Ctg, logtalk(abolish_category(Ctg), ExCtx)),
'$lgt_abolish_category_checked'(Ctg, ExCtx).
'$lgt_abolish_category_checked'(Ctg, ExCtx) :-
( '$lgt_current_category_'(Ctg, _, Dcl, Def, Rnm, Flags) ->
( Flags /\ 2 =:= 2 ->
% dynamic category
'$lgt_abolish_entity_predicates'(Def),
abolish(Dcl/4),
abolish(Dcl/5),
abolish(Def/3),
abolish(Def/4),
abolish(Rnm/3),
retractall('$lgt_current_category_'(Ctg, _, _, _, _, _)),
retractall('$lgt_entity_property_'(Ctg, _)),
retractall('$lgt_predicate_property_'(Ctg, _, _)),
retractall('$lgt_extends_category_'(Ctg, _, _)),
retractall('$lgt_implements_protocol_'(Ctg, _, _)),
retractall('$lgt_complemented_object_'(_, Ctg, _, _, _)),
'$lgt_clean_lookup_caches'
; throw(error(permission_error(modify, static_category, Ctg), logtalk(abolish_category(Ctg), ExCtx)))
)
; throw(error(existence_error(category, Ctg), logtalk(abolish_category(Ctg), ExCtx)))
).
% abolish_protocol(@protocol_identifier)
abolish_protocol(Ptc) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_abolish_protocol'(Ptc, ExCtx).
'$lgt_abolish_protocol'(Ptc, ExCtx) :-
'$lgt_check'(protocol_identifier, Ptc, logtalk(abolish_protocol(Ptc), ExCtx)),
'$lgt_abolish_protocol_checked'(Ptc, ExCtx).
'$lgt_abolish_protocol_checked'(Ptc, ExCtx) :-
( '$lgt_current_protocol_'(Ptc, _, Dcl, Rnm, Flags) ->
( Flags /\ 2 =:= 2 ->
% dynamic protocol
abolish(Dcl/4),
abolish(Dcl/5),
abolish(Rnm/3),
retractall('$lgt_current_protocol_'(Ptc, _, _, _, _)),
retractall('$lgt_entity_property_'(Ptc, _)),
retractall('$lgt_predicate_property_'(Ptc, _, _)),
retractall('$lgt_extends_protocol_'(Ptc, _, _)),
'$lgt_clean_lookup_caches'
; throw(error(permission_error(modify, static_protocol, Ptc), logtalk(abolish_protocol(Ptc), ExCtx)))
)
; throw(error(existence_error(protocol, Ptc), logtalk(abolish_protocol(Ptc), ExCtx)))
).
% '$lgt_abolish_entity_predicates'(+atom)
%
% auxiliary predicate used when abolishing objects and categories
'$lgt_abolish_entity_predicates'(Def) :-
call(Def, _, _, Call),
'$lgt_unwrap_compiled_head'(Call, Pred),
functor(Pred, Functor, Arity),
abolish(Functor/Arity),
fail.
'$lgt_abolish_entity_predicates'(_).
% implements_protocol(?object_identifier, ?protocol_identifier)
% implements_protocol(?category_identifier, ?protocol_identifier)
implements_protocol(ObjOrCtg, Ptc) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_implements_protocol'(ObjOrCtg, Ptc, ExCtx).
'$lgt_implements_protocol'(ObjOrCtg, Ptc, ExCtx) :-
'$lgt_check'(var_or_object_identifier, ObjOrCtg, logtalk(implements_protocol(ObjOrCtg, Ptc), ExCtx)),
'$lgt_check'(var_or_protocol_identifier, Ptc, logtalk(implements_protocol(ObjOrCtg, Ptc), ExCtx)),
'$lgt_implements_protocol_'(ObjOrCtg, Ptc, _).
% implements_protocol(?object_identifier, ?protocol_identifier, ?atom)
% implements_protocol(?category_identifier, ?protocol_identifier, ?atom)
implements_protocol(ObjOrCtg, Ptc, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_implements_protocol'(ObjOrCtg, Ptc, Scope, ExCtx).
'$lgt_implements_protocol'(ObjOrCtg, Ptc, Scope, ExCtx) :-
'$lgt_check'(var_or_object_identifier, ObjOrCtg, logtalk(implements_protocol(ObjOrCtg, Ptc, Scope), ExCtx)),
'$lgt_check'(var_or_protocol_identifier, Ptc, logtalk(implements_protocol(ObjOrCtg, Ptc, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(implements_protocol(ObjOrCtg, Ptc, Scope), ExCtx)),
'$lgt_implements_protocol_'(ObjOrCtg, Ptc, Scope).
% imports_category(?object_identifier, ?category_identifier)
imports_category(Obj, Ctg) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_imports_category'(Obj, Ctg, ExCtx).
'$lgt_imports_category'(Obj, Ctg, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Obj, logtalk(imports_category(Obj, Ctg), ExCtx)),
'$lgt_check'(var_or_category_identifier, Ctg, logtalk(imports_category(Obj, Ctg), ExCtx)),
'$lgt_imports_category_'(Obj, Ctg, _).
% imports_category(?object_identifier, ?category_identifier, ?atom)
imports_category(Obj, Ctg, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_imports_category'(Obj, Ctg, Scope, ExCtx).
'$lgt_imports_category'(Obj, Ctg, Scope, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Obj, logtalk(imports_category(Obj, Ctg, Scope), ExCtx)),
'$lgt_check'(var_or_category_identifier, Ctg, logtalk(imports_category(Obj, Ctg, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(imports_category(Obj, Ctg, Scope), ExCtx)),
'$lgt_imports_category_'(Obj, Ctg, Scope).
% instantiates_class(?object_identifier, ?object_identifier)
instantiates_class(Obj, Class) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_instantiates_class'(Obj, Class, ExCtx).
'$lgt_instantiates_class'(Obj, Class, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Obj, logtalk(instantiates_class(Obj, Class), ExCtx)),
'$lgt_check'(var_or_object_identifier, Class, logtalk(instantiates_class(Obj, Class), ExCtx)),
'$lgt_instantiates_class_'(Obj, Class, _).
% instantiates_class(?object_identifier, ?object_identifier, ?atom)
instantiates_class(Obj, Class, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_instantiates_class'(Obj, Class, Scope, ExCtx).
'$lgt_instantiates_class'(Obj, Class, Scope, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Obj, logtalk(instantiates_class(Obj, Class, Scope), ExCtx)),
'$lgt_check'(var_or_object_identifier, Class, logtalk(instantiates_class(Obj, Class, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(instantiates_class(Obj, Class, Scope), ExCtx)),
'$lgt_instantiates_class_'(Obj, Class, Scope).
% specializes_class(?object_identifier, ?object_identifier)
specializes_class(Class, Superclass) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_specializes_class'(Class, Superclass, ExCtx).
'$lgt_specializes_class'(Class, Superclass, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Class, logtalk(specializes_class(Class, Superclass), ExCtx)),
'$lgt_check'(var_or_object_identifier, Superclass, logtalk(specializes_class(Class, Superclass), ExCtx)),
'$lgt_specializes_class_'(Class, Superclass, _).
% specializes_class(?object_identifier, ?object_identifier, ?atom)
specializes_class(Class, Superclass, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_specializes_class'(Class, Superclass, Scope, ExCtx).
'$lgt_specializes_class'(Class, Superclass, Scope, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Class, logtalk(specializes_class(Class, Superclass, Scope), ExCtx)),
'$lgt_check'(var_or_object_identifier, Superclass, logtalk(specializes_class(Class, Superclass, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(specializes_class(Class, Superclass, Scope), ExCtx)),
'$lgt_specializes_class_'(Class, Superclass, Scope).
% extends_category(?category_identifier, ?category_identifier)
extends_category(Ctg, ExtCtg) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_extends_category'(Ctg, ExtCtg, ExCtx).
'$lgt_extends_category'(Ctg, ExtCtg, ExCtx) :-
'$lgt_check'(var_or_category_identifier, Ctg, logtalk(extends_category(Ctg, ExtCtg), ExCtx)),
'$lgt_check'(var_or_category_identifier, ExtCtg, logtalk(extends_category(Ctg, ExtCtg), ExCtx)),
'$lgt_extends_category_'(Ctg, ExtCtg, _).
% extends_category(?category_identifier, ?category_identifier, ?atom)
extends_category(Ctg, ExtCtg, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_extends_category'(Ctg, ExtCtg, Scope, ExCtx).
'$lgt_extends_category'(Ctg, ExtCtg, Scope, ExCtx) :-
'$lgt_check'(var_or_category_identifier, Ctg, logtalk(extends_category(Ctg, ExtCtg, Scope), ExCtx)),
'$lgt_check'(var_or_category_identifier, ExtCtg, logtalk(extends_category(Ctg, ExtCtg, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(extends_category(Ctg, ExtCtg, Scope), ExCtx)),
'$lgt_extends_category_'(Ctg, ExtCtg, Scope).
% extends_protocol(?protocol_identifier, ?protocol_identifier)
extends_protocol(Ptc, ExtPtc) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_extends_protocol'(Ptc, ExtPtc, ExCtx).
'$lgt_extends_protocol'(Ptc, ExtPtc, ExCtx) :-
'$lgt_check'(var_or_protocol_identifier, Ptc, logtalk(extends_protocol(Ptc, ExtPtc), ExCtx)),
'$lgt_check'(var_or_protocol_identifier, ExtPtc, logtalk(extends_protocol(Ptc, ExtPtc), ExCtx)),
'$lgt_extends_protocol_'(Ptc, ExtPtc, _).
% extends_protocol(?protocol_identifier, ?protocol_identifier, ?atom)
extends_protocol(Ptc, ExtPtc, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_extends_protocol'(Ptc, ExtPtc, Scope, ExCtx).
'$lgt_extends_protocol'(Ptc, ExtPtc, Scope, ExCtx) :-
'$lgt_check'(var_or_protocol_identifier, Ptc, logtalk(extends_protocol(Ptc, ExtPtc, Scope), ExCtx)),
'$lgt_check'(var_or_protocol_identifier, ExtPtc, logtalk(extends_protocol(Ptc, ExtPtc, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(extends_protocol(Ptc, ExtPtc, Scope), ExCtx)),
'$lgt_extends_protocol_'(Ptc, ExtPtc, Scope).
% extends_object(?object_identifier, ?object_identifier)
extends_object(Prototype, Parent) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_extends_object'(Prototype, Parent, ExCtx).
'$lgt_extends_object'(Prototype, Parent, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Prototype, logtalk(extends_object(Prototype, Parent), ExCtx)),
'$lgt_check'(var_or_object_identifier, Parent, logtalk(extends_object(Prototype, Parent), ExCtx)),
'$lgt_extends_object_'(Prototype, Parent, _).
% extends_object(?object_identifier, ?object_identifier, ?atom)
extends_object(Prototype, Parent, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_extends_object'(Prototype, Parent, Scope, ExCtx).
'$lgt_extends_object'(Prototype, Parent, Scope, ExCtx) :-
'$lgt_check'(var_or_object_identifier, Prototype, logtalk(extends_object(Prototype, Parent, Scope), ExCtx)),
'$lgt_check'(var_or_object_identifier, Parent, logtalk(extends_object(Prototype, Parent, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(extends_object(Prototype, Parent, Scope), ExCtx)),
'$lgt_extends_object_'(Prototype, Parent, Scope).
% complements_object(?category_identifier, ?object_identifier)
complements_object(Category, Object) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_complements_object'(Category, Object, ExCtx).
'$lgt_complements_object'(Category, Object, ExCtx) :-
'$lgt_check'(var_or_category_identifier, Category, logtalk(complements_object(Category, Object), ExCtx)),
'$lgt_check'(var_or_object_identifier, Object, logtalk(complements_object(Category, Object), ExCtx)),
'$lgt_complemented_object_'(Object, Category, _, _, _).
% conforms_to_protocol(?object_identifier, ?protocol_identifier)
% conforms_to_protocol(?category_identifier, ?protocol_identifier)
conforms_to_protocol(ObjOrCtg, Protocol) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_conforms_to_protocol'(ObjOrCtg, Protocol, ExCtx).
'$lgt_conforms_to_protocol'(ObjOrCtg, Protocol, ExCtx) :-
'$lgt_check'(var_or_object_identifier, ObjOrCtg, logtalk(conforms_to_protocol(ObjOrCtg, Protocol), ExCtx)),
'$lgt_check'(var_or_protocol_identifier, Protocol, logtalk(conforms_to_protocol(ObjOrCtg, Protocol), ExCtx)),
( var(ObjOrCtg) ->
'$lgt_conforms_to_protocol_checked'(ObjOrCtg, Protocol, _)
; var(Protocol) ->
'$lgt_conforms_to_protocol_checked'(ObjOrCtg, Protocol, _)
; % deterministic query
'$lgt_conforms_to_protocol_checked'(ObjOrCtg, Protocol, _),
!
).
% conforms_to_protocol(?object_identifier, ?protocol_identifier, ?atom)
% conforms_to_protocol(?category_identifier, ?protocol_identifier, ?atom)
conforms_to_protocol(ObjOrCtg, Protocol, Scope) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_conforms_to_protocol'(ObjOrCtg, Protocol, Scope, ExCtx).
'$lgt_conforms_to_protocol'(ObjOrCtg, Protocol, Scope, ExCtx) :-
'$lgt_check'(var_or_object_identifier, ObjOrCtg, logtalk(conforms_to_protocol(ObjOrCtg, Protocol, Scope), ExCtx)),
'$lgt_check'(var_or_protocol_identifier, Protocol, logtalk(conforms_to_protocol(ObjOrCtg, Protocol, Scope), ExCtx)),
'$lgt_check'(var_or_scope, Scope, logtalk(conforms_to_protocol(ObjOrCtg, Protocol, Scope), ExCtx)),
( var(ObjOrCtg) ->
'$lgt_conforms_to_protocol_checked'(ObjOrCtg, Protocol, Scope)
; var(Protocol) ->
'$lgt_conforms_to_protocol_checked'(ObjOrCtg, Protocol, Scope)
; % deterministic query
'$lgt_conforms_to_protocol_checked'(ObjOrCtg, Protocol, Scope),
!
).
'$lgt_conforms_to_protocol_checked'(Object, Protocol, Scope) :-
'$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
( \+ '$lgt_instantiates_class_'(Object, _, _),
\+ '$lgt_specializes_class_'(Object, _, _) ->
'$lgt_prototype_conforms_to_protocol'(Object, Protocol, Scope)
; '$lgt_instance_conforms_to_protocol'(Object, Protocol, Scope)
).
'$lgt_conforms_to_protocol_checked'(Category, Protocol, Scope) :-
'$lgt_current_category_'(Category, _, _, _, _, _),
'$lgt_category_conforms_to_protocol'(Category, Protocol, Scope).
'$lgt_prototype_conforms_to_protocol'(Prototype, Protocol, Scope) :-
'$lgt_complemented_object_'(Prototype, Category, _, _, _),
'$lgt_category_conforms_to_protocol'(Category, Protocol, Scope).
'$lgt_prototype_conforms_to_protocol'(Prototype, Protocol, Scope) :-
'$lgt_implements_protocol_'(Prototype, Protocol0, ImplementationScope),
( Protocol = Protocol0,
Scope = ImplementationScope
; '$lgt_protocol_conforms_to_protocol'(Protocol0, Protocol, InheritedScope),
'$lgt_filter_scope'(ImplementationScope, InheritedScope, Scope)
).
'$lgt_prototype_conforms_to_protocol'(Prototype, Protocol, Scope) :-
'$lgt_imports_category_'(Prototype, Category, ImportScope),
'$lgt_category_conforms_to_protocol'(Category, Protocol, InheritedScope),
'$lgt_filter_scope'(ImportScope, InheritedScope, Scope).
'$lgt_prototype_conforms_to_protocol'(Prototype, Protocol, Scope) :-
'$lgt_extends_object_'(Prototype, Parent, ExtensionScope),
'$lgt_prototype_conforms_to_protocol'(Parent, Protocol, InheritedScope),
'$lgt_filter_scope'(ExtensionScope, InheritedScope, Scope).
'$lgt_instance_conforms_to_protocol'(Instance, Protocol, Scope) :-
'$lgt_instantiates_class_'(Instance, Class, InstantiationScope),
'$lgt_class_conforms_to_protocol'(Class, Protocol, InheritedScope),
'$lgt_filter_scope'(InstantiationScope, InheritedScope, Scope).
'$lgt_class_conforms_to_protocol'(Class, Protocol, Scope) :-
'$lgt_complemented_object_'(Class, Category, _, _, _),
'$lgt_category_conforms_to_protocol'(Category, Protocol, Scope).
'$lgt_class_conforms_to_protocol'(Class, Protocol, Scope) :-
'$lgt_implements_protocol_'(Class, Protocol0, ImplementationScope),
( Protocol = Protocol0,
Scope = ImplementationScope
; '$lgt_protocol_conforms_to_protocol'(Protocol0, Protocol, InheritedScope),
'$lgt_filter_scope'(ImplementationScope, InheritedScope, Scope)
).
'$lgt_class_conforms_to_protocol'(Class, Protocol, Scope) :-
'$lgt_imports_category_'(Class, Category, ImportScope),
'$lgt_category_conforms_to_protocol'(Category, Protocol, InheritedScope),
'$lgt_filter_scope'(ImportScope, InheritedScope, Scope).
'$lgt_class_conforms_to_protocol'(Class, Protocol, Scope) :-
'$lgt_specializes_class_'(Class, Superclass, SpecializationScope),
'$lgt_class_conforms_to_protocol'(Superclass, Protocol, InheritedScope),
'$lgt_filter_scope'(SpecializationScope, InheritedScope, Scope).
'$lgt_protocol_conforms_to_protocol'(Protocol0, Protocol, Scope) :-
'$lgt_extends_protocol_'(Protocol0, Protocol1, ExtensionScope),
( Protocol = Protocol1,
Scope = ExtensionScope
; '$lgt_protocol_conforms_to_protocol'(Protocol1, Protocol, InheritedScope),
'$lgt_filter_scope'(ExtensionScope, InheritedScope, Scope)
).
'$lgt_category_conforms_to_protocol'(Category, Protocol, Scope) :-
'$lgt_implements_protocol_'(Category, Protocol0, ImplementationScope),
( Protocol = Protocol0,
Scope = ImplementationScope
; '$lgt_protocol_conforms_to_protocol'(Protocol0, Protocol, InheritedScope),
'$lgt_filter_scope'(ImplementationScope, InheritedScope, Scope)
).
'$lgt_category_conforms_to_protocol'(Category, Protocol, Scope) :-
'$lgt_extends_category_'(Category, ExtendedCategory, ExtensionScope),
'$lgt_category_conforms_to_protocol'(ExtendedCategory, Protocol, InheritedScope),
'$lgt_filter_scope'(ExtensionScope, InheritedScope, Scope).
% public relations don't change predicate scopes
'$lgt_filter_scope'((public), Scope, Scope).
% protected relations change public predicates to protected predicates
'$lgt_filter_scope'(protected, Scope, protected) :-
Scope \= (private).
% current_event(?event, ?term, ?term, ?term, ?object_identifier)
current_event(Event, Obj, Msg, Sender, Monitor) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_event'(Event, Obj, Msg, Sender, Monitor, ExCtx).
'$lgt_current_event'(Event, Obj, Msg, Sender, Monitor, ExCtx) :-
'$lgt_check'(var_or_event, Event, logtalk(current_event(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Obj, logtalk(current_event(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_callable, Msg, logtalk(current_event(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Sender, logtalk(current_event(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Monitor, logtalk(current_event(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_current_event_checked'(Event, Obj, Msg, Sender, Monitor).
'$lgt_current_event_checked'(before, Obj, Msg, Sender, Monitor) :-
'$lgt_before_event_'(Obj, Msg, Sender, Monitor, _).
'$lgt_current_event_checked'(after, Obj, Msg, Sender, Monitor) :-
'$lgt_after_event_'(Obj, Msg, Sender, Monitor, _).
% define_events(@term, @term, @term, @term, +object_identifier)
define_events(Event, Obj, Msg, Sender, Monitor) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_define_events'(Event, Obj, Msg, Sender, Monitor, ExCtx).
'$lgt_define_events'(Event, Obj, Msg, Sender, Monitor, ExCtx) :-
'$lgt_check'(var_or_event, Event, logtalk(define_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Obj, logtalk(define_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_callable, Msg, logtalk(define_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Sender, logtalk(define_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(object_identifier, Monitor, logtalk(define_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
( '$lgt_current_object_'(Monitor, _, _, Def, _, _, _, _, _, _, _) ->
'$lgt_execution_context'(MonitorExCtx, _, Monitor, Monitor, Monitor, [], []),
( var(Event) ->
'$lgt_define_events'(before, Obj, Msg, Sender, Monitor, Def, MonitorExCtx),
'$lgt_define_events'(after, Obj, Msg, Sender, Monitor, Def, MonitorExCtx)
; Event == before ->
'$lgt_define_events'(before, Obj, Msg, Sender, Monitor, Def, MonitorExCtx)
; % Event == after
'$lgt_define_events'(after, Obj, Msg, Sender, Monitor, Def, MonitorExCtx)
)
; throw(error(existence_error(object, Monitor), logtalk(define_events(Event, Obj, Msg, Sender, Monitor), ExCtx)))
).
'$lgt_define_events'(before, Obj, Msg, Sender, Monitor, Def, ExCtx) :-
( call(Def, before(Obj, Msg, Sender), ExCtx, Call, _, _) ->
retractall('$lgt_before_event_'(Obj, Msg, Sender, Monitor, _)),
assertz('$lgt_before_event_'(Obj, Msg, Sender, Monitor, Call))
; throw(error(existence_error(procedure, before/3), logtalk(define_events(before, Obj, Msg, Sender, Monitor), ExCtx)))
).
'$lgt_define_events'(after, Obj, Msg, Sender, Monitor, Def, ExCtx) :-
( call(Def, after(Obj, Msg, Sender), ExCtx, Call, _, _) ->
retractall('$lgt_after_event_'(Obj, Msg, Sender, Monitor, _)),
assertz('$lgt_after_event_'(Obj, Msg, Sender, Monitor, Call))
; throw(error(existence_error(procedure, after/3), logtalk(define_events(after, Obj, Msg, Sender, Monitor), ExCtx)))
).
% abolish_events(@term, @term, @term, @term, @term)
abolish_events(Event, Obj, Msg, Sender, Monitor) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_abolish_events'(Event, Obj, Msg, Sender, Monitor, ExCtx).
'$lgt_abolish_events'(Event, Obj, Msg, Sender, Monitor, ExCtx) :-
'$lgt_check'(var_or_event, Event, logtalk(abolish_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Obj, logtalk(abolish_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_callable, Msg, logtalk(abolish_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Sender, logtalk(abolish_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
'$lgt_check'(var_or_object_identifier, Monitor, logtalk(abolish_events(Event, Obj, Msg, Sender, Monitor), ExCtx)),
( var(Event) ->
retractall('$lgt_before_event_'(Obj, Msg, Sender, Monitor, _)),
retractall('$lgt_after_event_'(Obj, Msg, Sender, Monitor, _))
; Event == before ->
retractall('$lgt_before_event_'(Obj, Msg, Sender, Monitor, _))
; % Event == after
retractall('$lgt_after_event_'(Obj, Msg, Sender, Monitor, _))
).
% built-in multi-threading meta-predicates
% threaded(+callable)
threaded(Goals) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded(Goals), ExCtx))).
threaded(Goals) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_check'(qualified_callable, Goals, logtalk(threaded(Goals), ExCtx)),
'$lgt_compile_threaded_call'(Goals, MTGoals),
catch(MTGoals, Error, '$lgt_runtime_error_handler'(Error)).
% threaded_call(@callable, -nonvar)
threaded_call(Goal, Tag) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_call(Goal, Tag), ExCtx))).
threaded_call(Goal, Tag) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_call_tagged'(Goal, Goal, ExCtx, Tag), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_call(@callable)
threaded_call(Goal) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_call(Goal), ExCtx))).
threaded_call(Goal) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_call'(Goal, Goal, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_once(@callable, -nonvar)
threaded_once(Goal, Tag) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_once(Goal, Tag), ExCtx))).
threaded_once(Goal, Tag) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_once_tagged'(Goal, Goal, ExCtx, Tag), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_once(@callable)
threaded_once(Goal) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_once(Goal), ExCtx))).
threaded_once(Goal) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_once'(Goal, Goal, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_ignore(@callable)
threaded_ignore(Goal) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_ignore(Goal), ExCtx))).
threaded_ignore(Goal) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_ignore'(Goal, Goal, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_exit(+callable, +nonvar)
threaded_exit(Goal, Tag) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_exit(Goal, Tag), ExCtx))).
threaded_exit(Goal, Tag) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_exit_tagged'(Goal, ExCtx, Tag), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_exit(+callable)
threaded_exit(Goal) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_exit(Goal), ExCtx))).
threaded_exit(Goal) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_exit'(Goal, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_peek(+callable, +nonvar)
threaded_peek(Goal, Tag) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_peek(Goal, Tag), ExCtx))).
threaded_peek(Goal, Tag) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_peek_tagged'(Goal, ExCtx, Tag), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_peek(+callable)
threaded_peek(Goal) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_peek(Goal), ExCtx))).
threaded_peek(Goal) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_peek'(Goal, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_cancel(+nonvar)
threaded_cancel(Tag) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_cancel(Tag), ExCtx))).
threaded_cancel(Tag) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_cancel_tagged'(Tag, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_create(@term, @callable, ?nonvar)
threaded_engine_create(AnswerTemplate, Goal, Engine) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_create(AnswerTemplate, Goal, Engine), ExCtx))).
threaded_engine_create(AnswerTemplate, Goal, Engine) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_engine_create'(AnswerTemplate, Goal, Goal, ExCtx, Engine), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_self(?nonvar)
threaded_engine_self(Engine) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_self(Engine), ExCtx))).
threaded_engine_self(Engine) :-
'$lgt_threaded_engine_self'(user, Engine).
% threaded_engine(?nonvar)
threaded_engine(Engine) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine(Engine), ExCtx))).
threaded_engine(Engine) :-
'$lgt_current_engine'(user, Engine).
% threaded_engine_next(@nonvar, ?term)
threaded_engine_next(Engine, Answer) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_next(Engine, Answer), ExCtx))).
threaded_engine_next(Engine, Answer) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_engine_next'(Engine, Answer, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_next_reified(@nonvar, ?term)
threaded_engine_next_reified(Engine, Answer) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_next_reified(Engine, Answer), ExCtx))).
threaded_engine_next_reified(Engine, Answer) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_engine_next_reified'(Engine, Answer, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_yield(@term)
threaded_engine_yield(Answer) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_yield(Answer), ExCtx))).
threaded_engine_yield(Answer) :-
catch('$lgt_threaded_engine_yield'(Answer, user), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_post(@nonvar, @term)
threaded_engine_post(Engine, Term) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_post(Engine, Term), ExCtx))).
threaded_engine_post(Engine, Term) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_engine_post'(Engine, Term, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_fetch(?term)
threaded_engine_fetch(Term) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_fetch(Term), ExCtx))).
threaded_engine_fetch(Term) :-
catch('$lgt_threaded_engine_fetch'(Term, user), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_engine_destroy(+nonvar)
threaded_engine_destroy(Engine) :-
\+ '$lgt_prolog_feature'(engines, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(engines), logtalk(threaded_engine_destroy(Engine), ExCtx))).
threaded_engine_destroy(Engine) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
catch('$lgt_threaded_engine_destroy'(Engine, ExCtx), Error, '$lgt_runtime_error_handler'(Error)).
% threaded_wait(?nonvar)
threaded_wait(Message) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_wait(Message), ExCtx))).
threaded_wait(Message) :-
'$lgt_current_object_'(user, Prefix, _, _, _, _, _, _, _, _, _),
'$lgt_threaded_wait'(Message, Prefix).
% threaded_notify(@term)
threaded_notify(Message) :-
\+ '$lgt_prolog_feature'(threads, supported),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
throw(error(resource_error(threads), logtalk(threaded_notify(Message), ExCtx))).
threaded_notify(Message) :-
'$lgt_current_object_'(user, Prefix, _, _, _, _, _, _, _, _, _),
'$lgt_threaded_notify'(Message, Prefix).
% compiling and loading built-in predicates
% '$lgt_compiler_flag'(+atom, ?nonvar)
%
% gets/checks the current value of a compiler flag; the default flag
% values and the backend Prolog feature flags are cached at startup
'$lgt_compiler_flag'(Name, Value) :-
( '$lgt_pp_entity_compiler_flag_'(Name, CurrentValue) ->
% flag value as defined within the entity being compiled
Value = CurrentValue
; '$lgt_pp_file_compiler_flag_'(Name, CurrentValue) ->
% flag value as defined in the flags argument of the
% compiling/loading predicates or in the source file
Value = CurrentValue
; '$lgt_current_flag_'(Name, Value)
% default value for the current Logtalk session,
% cached or set by calls to the set_logtalk_flag/2 predicate
).
% logtalk_compile(@source_file_name)
% logtalk_compile(@list(source_file_name))
%
% compiles to disk a source file or list of source files using default flags
%
% top-level calls use the current working directory for resolving any relative
% source file paths while compiled calls in a source file use the source file
% directory by default
logtalk_compile(Files) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_directory'(Directory),
'$lgt_logtalk_compile'(Files, Directory, ExCtx).
'$lgt_logtalk_compile'(Files, Directory, ExCtx) :-
catch(
'$lgt_logtalk_compile_files'(Files, Directory),
error(Error, _),
'$lgt_logtalk_compile_error_handler'(Error, Files, ExCtx)
).
'$lgt_logtalk_compile_files'(Files, Directory) :-
'$lgt_init_warnings_counter'(logtalk_compile(Files)),
'$lgt_check_and_expand_source_files'(Files, ExpandedFiles),
'$lgt_compile_files'(ExpandedFiles, ['$relative_to'(Directory)]),
'$lgt_report_warning_numbers'(logtalk_compile(Files)),
'$lgt_clean_pp_file_clauses'.
'$lgt_logtalk_compile_error_handler'(Error, Files, ExCtx) :-
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
throw(error(Error, logtalk(logtalk_compile(Files), ExCtx))).
% logtalk_compile(@source_file_name, @list(compiler_flag))
% logtalk_compile(@list(source_file_name), @list(compiler_flag))
%
% compiles to disk a source file or a list of source files using a list of flags
%
% top-level calls use the current working directory for resolving any relative
% source file paths while compiled calls in a source file use the source file
% directory by default
%
% note that we can only clean the compiler flags after reporting warning numbers as the
% report/1 flag might be included in the list of flags but we cannot test for it as its
% value should only be used in the default code for printing messages
logtalk_compile(Files, Flags) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_directory'(Directory),
'$lgt_logtalk_compile'(Files, Flags, Directory, ExCtx).
'$lgt_logtalk_compile'(Files, Flags, Directory, ExCtx) :-
catch(
'$lgt_logtalk_compile_files'(Files, Flags, Directory),
error(Error, _),
'$lgt_logtalk_compile_error_handler'(Error, Files, Flags, ExCtx)
).
'$lgt_logtalk_compile_files'(Files, Flags, Directory) :-
'$lgt_init_warnings_counter'(logtalk_compile(Files, Flags)),
'$lgt_check_and_expand_source_files'(Files, ExpandedFiles),
'$lgt_check_compiler_flags'(Flags),
( '$lgt_member'(relative_to(_), Flags) ->
'$lgt_compile_files'(ExpandedFiles, Flags)
; '$lgt_compile_files'(ExpandedFiles, ['$relative_to'(Directory)| Flags])
),
'$lgt_report_warning_numbers'(logtalk_compile(Files, Flags)),
'$lgt_clean_pp_file_clauses'.
'$lgt_logtalk_compile_error_handler'(Error, Files, Flags, ExCtx) :-
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
throw(error(Error, logtalk(logtalk_compile(Files, Flags), ExCtx))).
% predicates for compilation warning counting and reporting
'$lgt_reset_warnings_counter' :-
retractall('$lgt_pp_warnings_top_goal_'(_)),
retractall('$lgt_pp_compiling_warnings_counter_'(_)),
retractall('$lgt_pp_loading_warnings_counter_'(_)).
'$lgt_init_warnings_counter'(Goal) :-
( '$lgt_pp_warnings_top_goal_'(_) ->
% not top compilation/loading goal; do nothing
true
; % remember top compilation/loading goal
assertz('$lgt_pp_warnings_top_goal_'(Goal)),
% initialize compilation warnings counter
retractall('$lgt_pp_compiling_warnings_counter_'(_)),
assertz('$lgt_pp_compiling_warnings_counter_'(0)),
% initialize loading warnings counter
retractall('$lgt_pp_loading_warnings_counter_'(_)),
assertz('$lgt_pp_loading_warnings_counter_'(0))
).
'$lgt_increment_compiling_warnings_counter' :-
once(retract('$lgt_pp_compiling_warnings_counter_'(Old))),
New is Old + 1,
assertz('$lgt_pp_compiling_warnings_counter_'(New)).
'$lgt_increment_loading_warnings_counter' :-
once(retract('$lgt_pp_loading_warnings_counter_'(Old))),
New is Old + 1,
assertz('$lgt_pp_loading_warnings_counter_'(New)).
'$lgt_report_warning_numbers'(Goal) :-
( retract('$lgt_pp_warnings_top_goal_'(Goal)),
% top compilation/loading goal
retract('$lgt_pp_compiling_warnings_counter_'(CCounter)),
retract('$lgt_pp_loading_warnings_counter_'(LCounter)) ->
% report compilation and loading warnings
'$lgt_print_message'(
comment(warnings),
compilation_and_loading_warnings(CCounter, LCounter)
)
; % not top compilation/loading goal
true
).
% '$lgt_check_and_expand_source_files'(@nonvar, -nonvar)
% '$lgt_check_and_expand_source_files'(@list, -list)
%
% check if the source file names are valid (but not if the file exists)
% and return their absolute paths when using library notation or when
% they start with an environment variable (assumes environment variables
% use POSIX syntax in Prolog internal file paths)
'$lgt_check_and_expand_source_files'([File| Files], [Path| Paths]) :-
!,
'$lgt_check_and_expand_source_file'(File, Path),
'$lgt_check_and_expand_source_files'(Files, Paths).
'$lgt_check_and_expand_source_files'([], []) :-
!.
'$lgt_check_and_expand_source_files'(File, Path) :-
'$lgt_check_and_expand_source_file'(File, Path).
'$lgt_check_and_expand_source_file'(File, Path) :-
( atom(File) ->
'$lgt_prolog_os_file_name'(NormalizedFile, File),
( sub_atom(NormalizedFile, 0, 1, _, '$') ->
'$lgt_expand_path'(NormalizedFile, Path)
; Path = NormalizedFile
)
; compound(File),
File =.. [Library, Basename],
atom(Basename) ->
% library notation
'$lgt_prolog_os_file_name'(NormalizedBasename, Basename),
( '$lgt_expand_library_alias'(Library, Directory) ->
atom_concat(Directory, NormalizedBasename, Path)
; throw(error(existence_error(library, Library), _))
)
; % invalid source file specification
ground(File) ->
throw(error(type_error(source_file_name, File), _))
; throw(error(instantiation_error, _))
).
% '$lgt_expand_library_alias'(+atom, -atom)
%
% converts a library alias into its corresponding path; uses a depth
% bound to prevent loops (inspired by similar code in SWI-Prolog)
'$lgt_expand_library_alias'(Library, Path) :-
'$lgt_expand_library_alias'(Library, Path0, 16),
% expand the library path into an absolute path as it may
% contain environment variables that need to be expanded
( sub_atom(Path0, 0, 1, _, '/') ->
% this covers the case of embedded applications created in a POSIX system
% and being run on a Windows system where a path starting with a slash
% would not be recognized as an absolute path by '$lgt_expand_path'/2
Path1 = Path0
; '$lgt_expand_path'(Path0, Path1)
),
% make sure that the library path ends with a slash
( sub_atom(Path1, _, 1, 0, '/') ->
Path = Path1
; atom_concat(Path1, '/', Path)
).
'$lgt_expand_library_alias'(Library, Path, Depth) :-
logtalk_library_path(Library, Location), !,
( compound(Location),
Location =.. [Prefix, Directory],
atom(Directory) ->
% assume library notation (a compound term)
Depth > 0,
NewDepth is Depth - 1,
'$lgt_expand_library_alias'(Prefix, PrefixPath0, NewDepth),
% make sure that the prefix path ends with a slash
( sub_atom(PrefixPath0, _, 1, 0, '/') ->
atom_concat(PrefixPath0, Directory, Path)
; atom_concat(PrefixPath0, '/', PrefixPath1),
atom_concat(PrefixPath1, Directory, Path)
)
; atom(Location) ->
% assume the final component of the library path
Path = Location
; ground(Location) ->
throw(error(type_error(library_path, Location), _))
; throw(error(instantiation_error, _))
).
% '$lgt_check_compiler_flags'(@list)
%
% checks if the compiler flags are valid
'$lgt_check_compiler_flags'([Flag| Flags]) :-
!,
( var(Flag) ->
throw(error(instantiation_error, _))
; Flag =.. [Name, Value] ->
'$lgt_check'(read_write_flag, Name, _),
'$lgt_check'(flag_value, Name+Value, _)
; % invalid flag syntax
compound(Flag) ->
throw(error(domain_error(compiler_flag, Flag), _))
; throw(error(type_error(compound, Flag), _))
),
'$lgt_check_compiler_flags'(Flags).
'$lgt_check_compiler_flags'([]) :-
!.
'$lgt_check_compiler_flags'(Flags) :-
throw(error(type_error(list, Flags), _)).
% '$lgt_set_compiler_flags'(@list)
%
% sets the compiler flags
'$lgt_set_compiler_flags'(Flags) :-
'$lgt_assert_compiler_flags'(Flags),
% only one of the optimize and debug flags can be turned on at the same time
( '$lgt_member'(optimize(on), Flags) ->
retractall('$lgt_pp_file_compiler_flag_'(debug, _)),
assertz('$lgt_pp_file_compiler_flag_'(debug, off))
; '$lgt_member'(debug(on), Flags) ->
retractall('$lgt_pp_file_compiler_flag_'(optimize, _)),
assertz('$lgt_pp_file_compiler_flag_'(optimize, off))
; '$lgt_member'(linter(Linter), Flags) ->
'$lgt_set_compiler_linter_flag'(Linter)
; true
),
( '$lgt_pp_file_compiler_flag_'(hook, HookEntity) ->
% pre-compile hooks in order to speed up entity compilation
( current_object(HookEntity) ->
'$lgt_comp_ctx'(Ctx, _, _, user, user, user, HookEntity, _, [], [], ExCtx, runtime, [], _, _),
'$lgt_execution_context'(ExCtx, user, user, user, HookEntity, [], []),
'$lgt_current_flag_'(events, Events),
'$lgt_compile_message_to_object'(term_expansion(Term, Terms), HookEntity, TermExpansionGoal, Events, Ctx),
'$lgt_compile_message_to_object'(goal_expansion(Goal, ExpandedGoal), HookEntity, GoalExpansionGoal, Events, Ctx)
; atom(HookEntity),
'$lgt_prolog_feature'(modules, supported),
current_module(HookEntity) ->
TermExpansionGoal = ':'(HookEntity, term_expansion(Term, Terms)),
GoalExpansionGoal = ':'(HookEntity, goal_expansion(Goal, ExpandedGoal))
; throw(error(existence_error(object, HookEntity), _))
),
retractall('$lgt_pp_hook_term_expansion_'(_, _)),
assertz((
'$lgt_pp_hook_term_expansion_'(Term, Terms) :-
catch(TermExpansionGoal, Error, '$lgt_term_expansion_error'(HookEntity, Term, Error))
)),
retractall('$lgt_pp_hook_goal_expansion_'(_, _)),
assertz((
'$lgt_pp_hook_goal_expansion_'(Goal, ExpandedGoal) :-
catch(GoalExpansionGoal, Error, '$lgt_goal_expansion_error'(HookEntity, Goal, Error))
))
; true
).
% term-expansion errors result in a warning message and a failure
'$lgt_term_expansion_error'(HookEntity, Term, Error) :-
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_loading_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(
warning(expansion),
term_expansion_error(File, Lines, Type, Entity, HookEntity, Term, Error)
)
; '$lgt_print_message'(
warning(expansion),
term_expansion_error(File, Lines, HookEntity, Term, Error)
)
),
fail.
% goal-expansion errors result in a warning message and a failure
'$lgt_goal_expansion_error'(HookEntity, Goal, Error) :-
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_loading_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(
warning(expansion),
goal_expansion_error(File, Lines, Type, Entity, HookEntity, Goal, Error)
)
; '$lgt_print_message'(
warning(expansion),
goal_expansion_error(File, Lines, HookEntity, Goal, Error)
)
),
fail.
'$lgt_assert_compiler_flags'([]).
'$lgt_assert_compiler_flags'([Flag| Flags]) :-
Flag =.. [Name, Value],
retractall('$lgt_pp_file_compiler_flag_'(Name, _)),
assertz('$lgt_pp_file_compiler_flag_'(Name, Value)),
'$lgt_assert_compiler_flags'(Flags).
% logtalk_load(@source_file_name)
% logtalk_load(@list(source_file_name))
%
% compiles to disk and then loads to memory a source file or a list of source
% files using default compiler flags
%
% top-level calls use the current working directory for resolving any relative
% source file paths while compiled calls in a source file use the source file
% directory by default
logtalk_load(Files) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_directory'(Directory),
'$lgt_logtalk_load'(Files, Directory, ExCtx).
'$lgt_logtalk_load'(Files, Directory, ExCtx) :-
catch(
'$lgt_logtalk_load_files'(Files, Directory),
error(Error, _),
'$lgt_logtalk_load_error_handler'(Error, Files, ExCtx)
).
'$lgt_logtalk_load_files'(Files, Directory) :-
'$lgt_init_warnings_counter'(logtalk_load(Files)),
'$lgt_check_and_expand_source_files'(Files, ExpandedFiles),
'$lgt_load_files'(ExpandedFiles, ['$relative_to'(Directory)]),
'$lgt_report_warning_numbers'(logtalk_load(Files)),
'$lgt_clean_pp_file_clauses'.
'$lgt_logtalk_load_error_handler'(Error, Files, ExCtx) :-
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
throw(error(Error, logtalk(logtalk_load(Files), ExCtx))).
% logtalk_load(@source_file_name, @list(compiler_flag))
% logtalk_load(@list(source_file_name), @list(compiler_flag))
%
% compiles to disk and then loads to memory a source file or a list of source
% files using a list of compiler flags
%
% top-level calls use the current working directory for resolving any relative
% source file paths while compiled calls in a source file use the source file
% directory by default
%
% note that we can only clean the compiler flags after reporting warning
% numbers as the report/1 flag might be in the list of flags but we cannot
% test for it as its value should only be used in the default code for
% printing messages
logtalk_load(Files, Flags) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_directory'(Directory),
'$lgt_logtalk_load'(Files, Flags, Directory, ExCtx).
'$lgt_logtalk_load'(Files, Flags, Directory, ExCtx) :-
catch(
'$lgt_logtalk_load_files'(Files, Flags, Directory),
error(Error, _),
'$lgt_logtalk_load_error_handler'(Error, Files, Flags, ExCtx)
).
'$lgt_logtalk_load_files'(Files, Flags, Directory) :-
'$lgt_init_warnings_counter'(logtalk_load(Files, Flags)),
'$lgt_check_and_expand_source_files'(Files, ExpandedFiles),
'$lgt_check_compiler_flags'(Flags),
( '$lgt_member'(relative_to(_), Flags) ->
'$lgt_load_files'(ExpandedFiles, Flags)
; '$lgt_load_files'(ExpandedFiles, ['$relative_to'(Directory)| Flags])
),
'$lgt_report_warning_numbers'(logtalk_load(Files, Flags)),
'$lgt_clean_pp_file_clauses'.
'$lgt_logtalk_load_error_handler'(Error, Files, Flags, ExCtx) :-
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
throw(error(Error, logtalk(logtalk_load(Files, Flags), ExCtx))).
% logtalk_make
%
% reloads all Logtalk source files that have been modified since the
% time they are last loaded
logtalk_make :-
logtalk_make(all).
% logtalk_make(+atom)
%
% performs a make target
logtalk_make(Target) :-
( var(Target) ->
'$lgt_print_message'(warning(make), no_make_target_specified),
fail
; '$lgt_valid_logtalk_make_target'(Target) ->
'$lgt_logtalk_make'(Target),
'$lgt_logtalk_make_target_actions'(Target)
; '$lgt_print_message'(warning(make), invalid_make_target(Target)),
fail
).
% reload of changed Logtalk source files
'$lgt_valid_logtalk_make_target'(all).
% recompile files in debug mode
'$lgt_valid_logtalk_make_target'(debug).
% recompile files in normal mode
'$lgt_valid_logtalk_make_target'(normal).
% recompile files in optimal mode
'$lgt_valid_logtalk_make_target'(optimal).
% clean all intermediate Prolog files
'$lgt_valid_logtalk_make_target'(clean).
% list missing entities and missing predicates
'$lgt_valid_logtalk_make_target'(check).
% list circular entity references
'$lgt_valid_logtalk_make_target'(circular).
% generate documentation
'$lgt_valid_logtalk_make_target'(documentation).
% clean dynamic binding caches
'$lgt_valid_logtalk_make_target'(caches).
'$lgt_logtalk_make_target_actions'(Target) :-
logtalk_make_target_action(Target),
fail.
'$lgt_logtalk_make_target_actions'(_).
% recompilation of source files that failed to load
'$lgt_logtalk_make'(all) :-
'$lgt_failed_file_'(Path),
% the following predicate may no longer be defined depending on what caused the failure
'$lgt_pp_file_paths_flags_'(_, _, Path, _, Flags),
'$lgt_file_exists'(Path),
logtalk_load(Path, Flags),
fail.
'$lgt_logtalk_make'(all) :-
'$lgt_failed_file_'(Path),
'$lgt_decompose_file_name'(Path, Directory, Name, Extension),
atom_concat(Name, Extension, Basename),
'$lgt_loaded_file_'(Basename, Directory, _, Flags, _, _, _),
% typically a descendant file failure propagated to a parent file
'$lgt_file_exists'(Path),
logtalk_load(Path, Flags),
fail.
% recompilation of changed source files since last loaded
'$lgt_logtalk_make'(all) :-
'$lgt_loaded_file_'(Basename, Directory, _, Flags, _, _, LoadingTimeStamp),
atom_concat(Directory, Basename, Path),
'$lgt_file_exists'(Path),
'$lgt_file_modification_time'(Path, CurrentTimeStamp),
LoadingTimeStamp @< CurrentTimeStamp,
\+ '$lgt_member'(reload(skip), Flags),
logtalk_load(Path, Flags),
fail.
% recompilation of included source files since last loaded
'$lgt_logtalk_make'(all) :-
'$lgt_included_file_'(Path, MainBasename, MainDirectory, LoadingTimeStamp),
'$lgt_file_exists'(Path),
'$lgt_file_modification_time'(Path, CurrentTimeStamp),
LoadingTimeStamp @< CurrentTimeStamp,
% force reloading by marking the main file loading as failed
atom_concat(MainDirectory, MainBasename, MainPath),
assertz('$lgt_failed_file_'(MainPath)),
'$lgt_loaded_file_'(MainBasename, MainDirectory, _, Flags, _, ObjectFile, _),
% ensure that the main file is recompiled so that it
% includes the contents of the modified include file
( '$lgt_file_exists'(ObjectFile) ->
'$lgt_delete_file'(ObjectFile)
; true
),
'$lgt_file_exists'(MainPath),
logtalk_load(MainPath, Flags),
fail.
% recompilation due to a change to the compilation mode (e.g. from "normal" to "debug")
'$lgt_logtalk_make'(all) :-
% find all files impacted by a change to compilation mode (this excludes all files
% that are compiled with an explicit compilation mode set using the corresponding
% compiler option)
findall(
file(Path, Flags),
( '$lgt_loaded_file_'(Basename, Directory, Mode, Flags, _, _, _),
'$lgt_changed_compilation_mode'(Mode, Flags),
atom_concat(Directory, Basename, Path)
),
Files
),
% filter files that will be reloaded by a parent file that will also be reloaded
'$lgt_member'(file(Path,Flags), Files),
\+ (
'$lgt_parent_file_'(Path, Parent),
'$lgt_member'(file(Parent,_), Files)
),
'$lgt_file_exists'(Path),
logtalk_load(Path, Flags),
fail.
'$lgt_logtalk_make'(all) :-
'$lgt_print_message'(comment(make), modified_files_reloaded).
'$lgt_logtalk_make'(debug) :-
'$lgt_print_message'(comment(make), reload_files_in_mode(debug)),
'$lgt_set_compiler_flag'(debug, on),
'$lgt_logtalk_make'(all).
'$lgt_logtalk_make'(normal) :-
'$lgt_print_message'(comment(make), reload_files_in_mode(normal)),
'$lgt_set_compiler_flag'(debug, off),
'$lgt_set_compiler_flag'(optimize, off),
'$lgt_logtalk_make'(all).
'$lgt_logtalk_make'(optimal) :-
'$lgt_print_message'(comment(make), reload_files_in_mode(optimal)),
'$lgt_set_compiler_flag'(optimize, on),
'$lgt_logtalk_make'(all).
'$lgt_logtalk_make'(clean) :-
'$lgt_loaded_file_'(_, _, _, _, _, ObjectFile, _),
'$lgt_delete_intermediate_files'(ObjectFile),
fail.
'$lgt_logtalk_make'(clean) :-
'$lgt_print_message'(comment(make), intermediate_files_deleted).
'$lgt_logtalk_make'(check) :-
'$lgt_print_message'(comment(make), scanning_for_missing_entities_predicates),
setof(Protocol, '$lgt_missing_protocol'(Protocol), Protocols),
'$lgt_print_message'(warning(make), missing_protocols(Protocols)),
fail.
'$lgt_logtalk_make'(check) :-
setof(Category, '$lgt_missing_category'(Category), Categories),
'$lgt_print_message'(warning(make), missing_categories(Categories)),
fail.
'$lgt_logtalk_make'(check) :-
setof(Object, '$lgt_missing_object'(Object), Objects),
'$lgt_print_message'(warning(make), missing_objects(Objects)),
fail.
'$lgt_logtalk_make'(check) :-
'$lgt_prolog_feature'(modules, supported),
setof(Module, '$lgt_missing_module'(Module), Modules),
'$lgt_print_message'(warning(make), missing_modules(Modules)),
fail.
'$lgt_logtalk_make'(check) :-
setof(Predicate, '$lgt_missing_predicate'(Predicate), Predicates),
'$lgt_print_message'(warning(make), missing_predicates(Predicates)),
fail.
'$lgt_logtalk_make'(check) :-
'$lgt_print_message'(comment(make), completed_scanning_for_missing_entities_predicates),
fail.
'$lgt_logtalk_make'(check) :-
'$lgt_print_message'(comment(make), scanning_for_duplicated_library_aliases),
findall(Alias, logtalk_library_path(Alias, _), Aliases),
setof(Duplicate, Rest^('$lgt_select'(Duplicate, Aliases, Rest), '$lgt_member'(Duplicate, Rest)), Duplicates),
'$lgt_print_message'(warning(make), duplicated_library_aliases(Duplicates)),
fail.
'$lgt_logtalk_make'(check) :-
'$lgt_print_message'(comment(make), scanning_for_library_paths_end_slash),
findall(Alias-Path, (logtalk_library_path(Alias, Path), atom(Path), \+ sub_atom(Path, _, 1, 0, '/')), Paths),
Paths \== [],
'$lgt_print_message'(warning(make), library_paths_dont_end_with_slash(Paths)),
fail.
'$lgt_logtalk_make'(check) :-
'$lgt_print_message'(comment(make), completed_scanning_of_library_alias_definitions).
'$lgt_logtalk_make'(circular) :-
'$lgt_print_message'(comment(make), scanning_for_circular_dependencies),
setof(CircularReference, '$lgt_circular_reference'(CircularReference), CircularReferences),
'$lgt_print_message'(warning(make), circular_references(CircularReferences)),
fail.
'$lgt_logtalk_make'(circular) :-
'$lgt_print_message'(comment(make), completed_scanning_for_circular_dependencies).
'$lgt_logtalk_make'(documentation) :-
'$lgt_print_message'(comment(make), running_all_defined_documentation_actions).
'$lgt_logtalk_make'(caches) :-
'$lgt_clean_lookup_caches',
'$lgt_print_message'(comment(make), dynamic_binding_caches_deleted).
% deal with changes to the default compilation mode
% when no explicit compilation mode as specified
'$lgt_changed_compilation_mode'(debug, Flags) :-
\+ '$lgt_member'(debug(_), Flags),
\+ '$lgt_compiler_flag'(debug, on).
'$lgt_changed_compilation_mode'(optimal, Flags) :-
\+ '$lgt_member'(optimize(_), Flags),
\+ '$lgt_compiler_flag'(optimize, on).
'$lgt_changed_compilation_mode'(normal, _) :-
( '$lgt_compiler_flag'(debug, on) ->
true
; '$lgt_compiler_flag'(optimize, on)
).
% find missing entities for logtalk_make(check)
'$lgt_missing_protocol'(Protocol-Reference) :-
'$lgt_implements_protocol_'(Entity, Protocol, _),
\+ '$lgt_current_protocol_'(Protocol, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_protocol'(Protocol-Reference) :-
'$lgt_extends_protocol_'(Entity, Protocol, _),
\+ '$lgt_current_protocol_'(Protocol, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_category'(Category-Reference) :-
'$lgt_imports_category_'(Entity, Category, _),
\+ '$lgt_current_category_'(Category, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_category'(Category-Reference) :-
'$lgt_extends_category_'(Entity, Category, _),
\+ '$lgt_current_category_'(Category, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_object'(Object-Reference) :-
'$lgt_extends_object_'(Entity, Object, _),
\+ '$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_object'(Object-Reference) :-
'$lgt_instantiates_class_'(Entity, Object, _),
\+ '$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_object'(Object-Reference) :-
'$lgt_specializes_class_'(Entity, Object, _),
\+ '$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_object'(Object-Reference) :-
'$lgt_complemented_object_'(Object, Entity, _, _, _),
\+ '$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Reference).
'$lgt_missing_object'(Object-Reference) :-
'$lgt_entity_property_'(Entity, calls(Object::_, _, _, _, Location)),
% note that the next call always fails when Object is not bound
\+ '$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
'$lgt_missing_reference'(Entity, Location, Reference).
'$lgt_missing_module'(Module-Reference) :-
'$lgt_entity_property_'(Entity, calls(':'(Module,_), _, _, _, Location)),
% note that the next call always fails when Module is not bound;
% given the call, assume that the backend compiler supports modules
\+ current_module(Module),
'$lgt_missing_reference'(Entity, Location, Reference).
% find missing predicates for logtalk_make(check)
'$lgt_missing_predicate'((Object::Predicate)-Reference) :-
'$lgt_entity_property_'(Entity, calls(Object::Predicate, _, _, _, Location)),
% the object may only be known at runtime; reject those cases
nonvar(Object),
% require loaded objects as the missing objects are already listed
'$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
% ignore objects that can forward the predicates calls
\+ '$lgt_implements_protocol_'(Object, forwarding, _),
\+ '$lgt_current_predicate'(Object, Predicate, Entity, p(p(p)), _),
'$lgt_missing_reference'(Entity, Location, Reference).
'$lgt_missing_predicate'((^^Functor/Arity)-Reference) :-
'$lgt_entity_property_'(Entity, calls(^^Functor/Arity, _, _, _, Location)),
functor(Template, Functor, Arity),
( '$lgt_current_object_'(Entity, _, Dcl, _, _, IDcl, _, _, _, _, _) ->
( \+ '$lgt_instantiates_class_'(Entity, _, _),
\+ '$lgt_specializes_class_'(Entity, _, _) ->
% prototype
\+ call(Dcl, Template, _, _, _, _, _)
; % instance and/or class
\+ call(Dcl, Template, _, _, _, _, _),
\+ call(IDcl, Template, _, _, _, _, _)
)
; '$lgt_current_category_'(Entity, _, Dcl, _, _, _),
\+ call(Dcl, Template, _, _, _, _)
),
'$lgt_missing_reference'(Entity, Location, Reference).
'$lgt_missing_predicate'((::Functor/Arity)-Reference) :-
'$lgt_entity_property_'(Entity, calls(::Functor/Arity, _, _, _, Location)),
functor(Template, Functor, Arity),
( '$lgt_current_object_'(Entity, _, Dcl, _, _, IDcl, _, _, _, _, _) ->
( \+ '$lgt_instantiates_class_'(Entity, _, _),
\+ '$lgt_specializes_class_'(Entity, _, _) ->
% prototype
\+ call(Dcl, Template, _, _, _, _, _)
; % instance and/or class
\+ call(Dcl, Template, _, _, _, _, _),
\+ call(IDcl, Template, _, _, _, _, _)
)
; '$lgt_current_category_'(Entity, _, Dcl, _, _, _),
\+ call(Dcl, Template, _, _, _, _)
),
'$lgt_missing_reference'(Entity, Location, Reference).
'$lgt_missing_predicate'((Functor/Arity)-Reference) :-
'$lgt_entity_property_'(Entity, calls(Functor/Arity, _, _, _, Location)),
( '$lgt_current_object_'(Entity, _, Dcl, Def, _, _, _, DDcl, DDef, _, Flags) ->
\+ '$lgt_object_property_declares'(Entity, Dcl, DDcl, Flags, Functor/Arity, _),
\+ '$lgt_object_property_defines'(Entity, Def, DDef, Functor/Arity, Flags, _)
; '$lgt_current_category_'(Entity, _, Dcl, Def, _, Flags),
\+ '$lgt_category_property_declares'(Entity, Dcl, Functor/Arity, _),
\+ '$lgt_category_property_defines'(Entity, Def, Functor/Arity, Flags, _)
),
'$lgt_missing_reference'(Entity, Location, Reference).
'$lgt_missing_predicate'((':'(Module,Predicate))-Reference) :-
'$lgt_prolog_feature'(modules, supported),
'$lgt_entity_property_'(Entity, calls(':'(Module,Predicate), _, _, _, Location)),
% the module may only be known at runtime; reject those cases
nonvar(Module),
% require loaded modules as the missing modules are already listed
current_module(Module),
\+ '$lgt_current_module_predicate'(Module, Predicate),
'$lgt_missing_reference'(Entity, Location, Reference).
% construct reference term for missing entities and predicates
'$lgt_missing_reference'(Entity, reference(Kind,Entity,Path,StartLine)) :-
% find the entity type
( '$lgt_current_protocol_'(Entity, _, _, _, _) ->
Kind = protocol
; '$lgt_current_category_'(Entity, _, _, _, _, _) ->
Kind = category
; '$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, _),
Kind = object
),
% find the reference file and line
( '$lgt_entity_property_'(Entity, file_lines(File, Directory, StartLine, _)) ->
atom_concat(Directory, File, Path)
; % dynamically created entity
Path = '',
StartLine = -1
).
'$lgt_missing_reference'(Entity, Location, reference(Kind,Entity,Path,StartLine)) :-
% find the entity type
( '$lgt_current_protocol_'(Entity, _, _, _, _) ->
Kind = protocol
; '$lgt_current_category_'(Entity, _, _, _, _, _) ->
Kind = category
; '$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, _),
Kind = object
),
% find the reference file and line
( Location = include(Path, StartLine-_) ->
% reference found in included file
true
; Location = StartLine-_,
( '$lgt_entity_property_'(Entity, file_lines(File, Directory, _, _)) ->
atom_concat(Directory, File, Path)
; % dynamically created entity
Path = ''
)
).
% find circular dependencies for logtalk_make(circular); we only check
% for mutual and triangular dependencies due to the computational cost
'$lgt_circular_reference'((Object1-Object2)-references([Path1-Line1,Path2-Line2])) :-
'$lgt_current_object_'(Object1, _, _, _, _, _, _, _, _, _, _),
'$lgt_current_object_'(Object2, _, _, _, _, _, _, _, _, _, _),
Object1 \== Object2,
functor(Object1, Functor1, Arity1),
functor(Object2, Functor2, Arity2),
Functor1-Arity1 @< Functor2-Arity2,
( '$lgt_entity_property_'(Object1, calls(Entity2::_, _, _, _, Line1)),
nonvar(Entity2), Entity2 = Object2,
'$lgt_entity_property_'(Object2, calls(Entity1::_, _, _, _, Line2)),
nonvar(Entity1), Entity1 = Object1 ->
true
; fail
),
'$lgt_circular_reference_object_path'(Object1, Path1),
'$lgt_circular_reference_object_path'(Object2, Path2).
'$lgt_circular_reference'((Object1-Object2-Object3)-references([Path1-Line1,Path2-Line2,Path3-Line3])) :-
'$lgt_current_object_'(Object1, _, _, _, _, _, _, _, _, _, _),
'$lgt_current_object_'(Object2, _, _, _, _, _, _, _, _, _, _),
Object1 \== Object2,
'$lgt_current_object_'(Object3, _, _, _, _, _, _, _, _, _, _),
Object1 \== Object3,
Object2 \== Object3,
functor(Object1, Functor1, Arity1),
functor(Object2, Functor2, Arity2),
Functor1-Arity1 @< Functor2-Arity2,
functor(Object3, Functor3, Arity3),
Functor2-Arity2 @< Functor3-Arity3,
( '$lgt_entity_property_'(Object1, calls(Entity2::_, _, _, _, Line1)),
nonvar(Entity2), Entity2 = Object2,
'$lgt_entity_property_'(Object2, calls(Entity3::_, _, _, _, Line2)),
nonvar(Entity3), Entity3 = Object3,
'$lgt_entity_property_'(Object3, calls(Entity1::_, _, _, _, Line3)),
nonvar(Entity1), Entity1 = Object1 ->
true
; fail
),
'$lgt_circular_reference_object_path'(Object1, Path1),
'$lgt_circular_reference_object_path'(Object2, Path2),
'$lgt_circular_reference_object_path'(Object3, Path3).
'$lgt_circular_reference_object_path'(Object, Path) :-
( '$lgt_entity_property_'(Object, file_lines(File, Directory, _, _)) ->
atom_concat(Directory, File, Path)
; Path = ''
).
% logtalk_load_context(?atom, ?nonvar)
%
% provides access to the compilation/loading context
%
% this predicate is the Logtalk version of the prolog_load_context/2
% predicate found on some compilers such as Quintus Prolog, SICStus
% Prolog, SWI-Prolog, and YAP
%
% when called from initialization/1 directives, calls to this predicate
% are resolved at compile time when the key is instantiated
logtalk_load_context(Key, Value) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_logtalk_load_context'(Key, Value, ExCtx).
'$lgt_logtalk_load_context'(Key, Value, ExCtx) :-
( var(Key) ->
'$lgt_logtalk_load_context_checked'(Key, Value)
; '$lgt_valid_logtalk_load_context_key'(Key) ->
'$lgt_logtalk_load_context_checked'(Key, Value)
; callable(Key) ->
throw(error(domain_error(logtalk_load_context_key, Key), logtalk(logtalk_load_context(Key, Value), ExCtx)))
; throw(error(type_error(callable, Key), logtalk(logtalk_load_context(Key, Value), ExCtx)))
).
'$lgt_logtalk_load_context_checked'(source, SourceFile) :-
'$lgt_pp_file_paths_flags_'(_, _, SourceFile, _, _).
'$lgt_logtalk_load_context_checked'(directory, Directory) :-
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _).
'$lgt_logtalk_load_context_checked'(basename, Basename) :-
'$lgt_pp_file_paths_flags_'(Basename, _, _, _, _).
'$lgt_logtalk_load_context_checked'(target, ObjectFile) :-
% full path of the generated intermediate Prolog file
'$lgt_pp_file_paths_flags_'(_, _, _, ObjectFile, _).
'$lgt_logtalk_load_context_checked'(flags, Flags) :-
% only returns the explicit flags passed in the second argument
% of the logtalk_compile/2 and logtalk_load/2 predicates
'$lgt_pp_file_paths_flags_'(_, _, _, _, Flags).
'$lgt_logtalk_load_context_checked'(entity_name, Entity) :-
% deprecated key; use entity_identifier key instead
'$lgt_pp_entity_'(_, Entity, _).
'$lgt_logtalk_load_context_checked'(entity_identifier, Entity) :-
'$lgt_pp_entity_'(_, Entity, _).
'$lgt_logtalk_load_context_checked'(entity_prefix, Prefix) :-
'$lgt_pp_entity_'(_, _, Prefix).
'$lgt_logtalk_load_context_checked'(entity_type, Type) :-
( '$lgt_pp_module_'(_) ->
Type = module
; '$lgt_pp_entity_'(Type, _, _)
).
'$lgt_logtalk_load_context_checked'(entity_relation, Relation) :-
'$lgt_logtalk_load_context_entity_relation'(Relation).
'$lgt_logtalk_load_context_checked'(term, Term) :-
% full file term being compiled
'$lgt_pp_term_source_data_'(Term, _, _, _, _).
'$lgt_logtalk_load_context_checked'(variables, Variables) :-
% variables of the full file term being compiled
'$lgt_pp_term_source_data_'(Term, _, _, _, _),
term_variables(Term, Variables).
'$lgt_logtalk_load_context_checked'(variable_names, VariableNames) :-
% variable names for the full file term being compiled
'$lgt_pp_term_source_data_'(_, VariableNames, _, _, _).
'$lgt_logtalk_load_context_checked'(variable_names(Term), VariableNames) :-
% variable names for the full file term being compiled
'$lgt_pp_term_source_data_'(Term, VariableNames, _, _, _).
'$lgt_logtalk_load_context_checked'(singletons, Singletons) :-
% singleton variables in the full file term being compiled
'$lgt_pp_term_source_data_'(_, _, Singletons, _, _).
'$lgt_logtalk_load_context_checked'(singletons(Term), Singletons) :-
% singleton variables in the full file term being compiled
'$lgt_pp_term_source_data_'(Term, _, Singletons, _, _).
'$lgt_logtalk_load_context_checked'(parameter_variables, ParameterVariablePairs) :-
% only succeeds when compiling a parametric entity containing parameter variables
'$lgt_pp_parameter_variables_'(ParameterVariablePairs).
'$lgt_logtalk_load_context_checked'(file, File) :-
% when compiling terms from an included file, this key returns the full
% path of the included file unlike the "source" key which always returns
% the full path of the main file
'$lgt_pp_term_source_data_'(_, _, _, File, _).
'$lgt_logtalk_load_context_checked'(term_position, Lines) :-
% term position of the full file term being compiled
'$lgt_pp_term_source_data_'(_, _, _, _, Lines).
'$lgt_logtalk_load_context_checked'(stream, Stream) :-
% avoid a spurious choice-point with some backend Prolog compilers
stream_property(Stream, alias(logtalk_compiler_input)), !.
'$lgt_logtalk_load_context_entity_relation'(extends_protocol(Ptc, ExtPtc, Scope)) :-
'$lgt_pp_extended_protocol_'(ExtPtc, Ptc, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(implements_protocol(ObjOrCtg, Ptc, Scope)) :-
'$lgt_pp_implemented_protocol_'(Ptc, ObjOrCtg, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(extends_category(Ctg, ExtCtg, Scope)) :-
'$lgt_pp_extended_category_'(ExtCtg, Ctg, _, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(imports_category(Obj, Ctg, Scope)) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(extends_object(Prototype, Parent, Scope)) :-
'$lgt_pp_extended_object_'(Parent, Prototype, _, _, _, _, _, _, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(instantiates_class(Obj, Class, Scope)) :-
'$lgt_pp_instantiated_class_'(Class, Obj, _, _, _, _, _, _, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(specializes_class(Class, Superclass, Scope)) :-
'$lgt_pp_specialized_class_'(Superclass, Class, _, _, _, _, _, _, _, _, Scope).
'$lgt_logtalk_load_context_entity_relation'(complements_object(Ctg, Obj)) :-
'$lgt_pp_complemented_object_'(Obj, Ctg, _, _, _).
% lgt_valid_logtalk_load_context_key(@nonvar)
'$lgt_valid_logtalk_load_context_key'(entity_identifier).
'$lgt_valid_logtalk_load_context_key'(entity_prefix).
'$lgt_valid_logtalk_load_context_key'(entity_type).
'$lgt_valid_logtalk_load_context_key'(entity_relation).
'$lgt_valid_logtalk_load_context_key'(source).
'$lgt_valid_logtalk_load_context_key'(file).
'$lgt_valid_logtalk_load_context_key'(basename).
'$lgt_valid_logtalk_load_context_key'(directory).
'$lgt_valid_logtalk_load_context_key'(stream).
'$lgt_valid_logtalk_load_context_key'(target).
'$lgt_valid_logtalk_load_context_key'(flags).
'$lgt_valid_logtalk_load_context_key'(term).
'$lgt_valid_logtalk_load_context_key'(term_position).
'$lgt_valid_logtalk_load_context_key'(variables).
'$lgt_valid_logtalk_load_context_key'(parameter_variables).
'$lgt_valid_logtalk_load_context_key'(variable_names).
'$lgt_valid_logtalk_load_context_key'(variable_names(_)).
'$lgt_valid_logtalk_load_context_key'(singletons).
'$lgt_valid_logtalk_load_context_key'(singletons(_)).
% set_logtalk_flag(+atom, +nonvar)
%
% sets a global flag value
%
% global flag values can always be overridden when compiling and loading source
% files by using either a set_logtalk_flag/2 directive (whose scope is local to
% the file or the entity containing it) or by passing a list of flag values in
% the calls to the logtalk_compile/2 and logtalk_load/2 predicates
set_logtalk_flag(Flag, Value) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_set_logtalk_flag'(Flag, Value, ExCtx).
'$lgt_set_logtalk_flag'(Flag, Value, ExCtx) :-
'$lgt_check'(read_write_flag, Flag, logtalk(set_logtalk_flag(Flag, Value), ExCtx)),
'$lgt_check'(flag_value, Flag + Value, logtalk(set_logtalk_flag(Flag, Value), ExCtx)),
'$lgt_set_compiler_flag'(Flag, Value).
'$lgt_set_compiler_flag'(optimize, Value) :-
!,
retractall('$lgt_current_flag_'(optimize, _)),
assertz('$lgt_current_flag_'(optimize, Value)),
'$lgt_clean_lookup_caches',
% only one of the optimize and debug flags can be turned on at the same time
( Value == on ->
retractall('$lgt_current_flag_'(debug, _)),
assertz('$lgt_current_flag_'(debug, off))
; true
).
'$lgt_set_compiler_flag'(debug, Value) :-
!,
retractall('$lgt_current_flag_'(debug, _)),
assertz('$lgt_current_flag_'(debug, Value)),
'$lgt_clean_lookup_caches',
% only one of the optimize and debug flags can be turned on at the same time
( Value == on ->
retractall('$lgt_current_flag_'(optimize, _)),
assertz('$lgt_current_flag_'(optimize, off))
; true
).
'$lgt_set_compiler_flag'(hook, Value) :-
!,
retractall('$lgt_current_flag_'(hook, _)),
assertz('$lgt_current_flag_'(hook, Value)),
% pre-compile hook calls for better performance when compiling files
'$lgt_compile_hooks'(Value).
'$lgt_set_compiler_flag'(linter, Value) :-
!,
'$lgt_set_compiler_linter_flag'(Value).
'$lgt_set_compiler_flag'(Flag, Value) :-
retractall('$lgt_current_flag_'(Flag, _)),
assertz('$lgt_current_flag_'(Flag, Value)).
'$lgt_set_compiler_linter_flag'(on) :-
forall(
'$lgt_linter_flag'(Flag),
'$lgt_set_compiler_flag'(Flag, warning)
).
'$lgt_set_compiler_linter_flag'(default) :-
forall(
'$lgt_linter_flag'(Flag),
( '$lgt_default_flag'(Flag, Default),
'$lgt_set_compiler_flag'(Flag, Default)
)
).
'$lgt_set_compiler_linter_flag'(off) :-
forall(
'$lgt_linter_flag'(Flag),
'$lgt_set_compiler_flag'(Flag, silent)
).
% current_logtalk_flag(?atom, ?nonvar)
%
% tests/gets flag values
current_logtalk_flag(Flag, Value) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_current_logtalk_flag'(Flag, Value, ExCtx).
'$lgt_current_logtalk_flag'(Flag, Value, ExCtx) :-
( var(Flag) ->
% enumerate, by backtracking, existing flags
( '$lgt_valid_flag'(Flag)
; '$lgt_user_defined_flag_'(Flag, _, _)
),
'$lgt_compiler_flag'(Flag, Value)
; '$lgt_valid_flag'(Flag) ->
'$lgt_compiler_flag'(Flag, Value)
; '$lgt_user_defined_flag_'(Flag, _, _) ->
'$lgt_compiler_flag'(Flag, Value)
; % invalid flag; generate error
'$lgt_check'(flag, Flag, logtalk(current_logtalk_flag(Flag, Value), ExCtx))
).
% create_logtalk_flag(+atom, +ground, +list)
%
% creates a new flag
%
% based on the specification of the create_prolog_flag/3
% built-in predicate of SWI-Prolog
create_logtalk_flag(Flag, Value, Options) :-
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []),
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx).
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx) :-
'$lgt_check'(atom, Flag, logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx)),
'$lgt_check'(ground, Value, logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx)),
'$lgt_check'(ground, Options, logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx)),
'$lgt_check'(list, Options, logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx)),
fail.
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx) :-
'$lgt_valid_flag'(Flag),
throw(error(permission_error(modify,flag,Flag), logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx))).
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx) :-
'$lgt_member'(Option, Options),
Option \= access(_),
Option \= keep(_),
Option \= type(_),
throw(error(domain_error(flag_option,Option), logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx))).
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx) :-
'$lgt_member'(access(Access), Options),
Access \== read_write,
Access \== read_only,
throw(error(domain_error(flag_option,access(Access)), logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx))).
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx) :-
'$lgt_member'(keep(Keep), Options),
Keep \== true,
Keep \== false,
throw(error(domain_error(flag_option,keep(Keep)), logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx))).
'$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx) :-
'$lgt_member'(type(Type0), Options),
( '$lgt_map_user_defined_flag_type'(Type0, Type) ->
( call(Type, Value) ->
fail
; throw(error(type_error(Type0,Value), logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx)))
)
; throw(error(domain_error(flag_option,type(Type0)), logtalk(create_logtalk_flag(Flag, Value, Options), ExCtx)))
).
'$lgt_create_logtalk_flag'(Flag, _, Options, _) :-
'$lgt_user_defined_flag_'(Flag, _, _),
'$lgt_member'(keep(true), Options),
!.
'$lgt_create_logtalk_flag'(Flag, Value, Options, _) :-
( '$lgt_member'(access(Access), Options) ->
true
; Access = read_write
),
( '$lgt_member'(type(Type0), Options) ->
'$lgt_map_user_defined_flag_type'(Type0, Type)
; % infer type from the initial value
Value == true ->
Type = '$lgt_is_boolean'
; Value == false ->
Type = '$lgt_is_boolean'
; atom(Value) ->
Type = atom
; integer(Value) ->
Type = integer
; float(Value) ->
Type = float
; % catchall
Type = ground
),
retractall('$lgt_user_defined_flag_'(Flag, _, _)),
assertz('$lgt_user_defined_flag_'(Flag, Access, Type)),
retractall('$lgt_current_flag_'(Flag, _)),
assertz('$lgt_current_flag_'(Flag, Value)).
% map the flag type to a closure that can be called with the flag
% value as argument for type-checking
'$lgt_map_user_defined_flag_type'(boolean, '$lgt_is_boolean').
'$lgt_map_user_defined_flag_type'(atom, atom).
'$lgt_map_user_defined_flag_type'(integer, integer).
'$lgt_map_user_defined_flag_type'(float, float).
'$lgt_map_user_defined_flag_type'(term, ground).
% '$lgt_version_data'(?compound)
%
% current Logtalk version for use with the current_logtalk_flag/2 predicate
%
% the last argument is an atom: 'aNN' for alpha versions, 'bNN' for beta
% versions, 'rcNN' for release candidates (with N being a decimal digit),
% and 'stable' for stable versions
'$lgt_version_data'(logtalk(3, 85, 0, stable)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% built-in methods
%
% calls to these methods are always compiled
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_object_exists'(@var, +callable, +execution_context)
% '$lgt_object_exists'(+object_identifier, +callable, +execution_context)
%
% checks if an object exists at runtime; this is necessary in order to
% prevent trivial messages such as true/0 or repeat/0 from succeeding
% when the target object doesn't exist; used in the compilation of ::/2
% calls
'$lgt_object_exists'(Obj, Pred, ExCtx) :-
( var(Obj) ->
throw(error(instantiation_error, logtalk(Obj::Pred, ExCtx)))
; '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _) ->
true
; % we have already verified that we have is a valid object identifier
% when we generated calls to this predicate
throw(error(existence_error(object, Obj), logtalk(Obj::Pred, ExCtx)))
).
% '$lgt_current_op'(+object_identifier, ?operator_priority, ?operator_specifier, ?atom, +object_identifier, +scope, @execution_context)
%
% current_op/3 built-in method
%
% local operator declarations without a scope declaration are invisible
'$lgt_current_op'(Obj, Priority, Specifier, Operator, Sender, Scope, ExCtx) :-
'$lgt_check'(object, Obj, logtalk(Obj::current_op(Priority, Specifier, Operator), ExCtx)),
'$lgt_check'(var_or_operator_priority, Priority, logtalk(current_op(Priority, Specifier, Operator), ExCtx)),
'$lgt_check'(var_or_operator_specifier, Specifier, logtalk(current_op(Priority, Specifier, Operator), ExCtx)),
'$lgt_check'(var_or_atom, Operator, logtalk(current_op(Priority, Specifier, Operator), ExCtx)),
( Obj == user ->
current_op(Priority, Specifier, Operator)
; '$lgt_entity_property_'(Obj, op(Priority, Specifier, Operator, OpScope)),
% don't return local operator declarations
OpScope \== l,
% check that the operator declaration is within the scope of the caller
\+ \+ (OpScope = Scope; Obj = Sender)
; % also return global operators that aren't overridden by entity operators
current_op(Priority, Specifier, Operator),
\+ (
'$lgt_entity_property_'(Obj, op(_, OtherSpecifier, Operator, _)),
'$lgt_same_operator_class'(Specifier, OtherSpecifier)
)
).
% '$lgt_current_predicate'(+object_identifier, ?predicate_indicator, +object_identifier, +scope, @execution_context)
%
% current_predicate/1 built-in method
%
% local predicates without a scope declaration are invisible
'$lgt_current_predicate'(Obj, Pred, _, _, ExCtx) :-
'$lgt_check'(var_or_predicate_indicator, Pred, logtalk(current_predicate(Pred), ExCtx)),
'$lgt_check'(object, Obj, logtalk(Obj::current_predicate(Pred), ExCtx)),
fail.
'$lgt_current_predicate'(user, Pred, _, _, _) :-
!,
current_predicate(Pred).
'$lgt_current_predicate'(Obj, Functor/Arity, Obj, _, ExCtx) :-
ground(Functor/Arity),
functor(Head, Functor, Arity),
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, _, _, Head, Ctx)
; '$lgt_use_module_predicate_'(Entity, _, _, Head, Ctx)
),
!.
'$lgt_current_predicate'(Obj, Functor/Arity, Sender, LookupScope, _) :-
ground(Functor/Arity),
!,
% make the current_predicate/1 method deterministic when its argument is ground
'$lgt_current_object_'(Obj, _, Dcl, _, _, _, _, _, _, _, _),
( call(Dcl, Pred, PredScope, _, _, SCtn, _),
functor(Pred, Functor, Arity) ->
% commit to the first solution found as an inherited
% predicate can always be re-declared
( \+ \+ PredScope = LookupScope ->
true
; Sender = SCtn
)
; fail
).
'$lgt_current_predicate'(Obj, Functor/Arity, Sender, LookupScope, _) :-
'$lgt_current_object_'(Obj, _, Dcl, _, _, _, _, _, _, _, _),
% use findall/3 + sort/2 to avoid a setof/3 call with five
% existentially-qualified variables or an auxiliary predicate
findall(Functor/Arity, (call(Dcl, Pred, _, _, _, _, _), functor(Pred, Functor, Arity)), Preds),
sort(Preds, SortedPreds),
'$lgt_member'(Functor/Arity, SortedPreds),
functor(Pred, Functor, Arity),
( call(Dcl, Pred, PredScope, _, _, SCtn, _) ->
% commit to the first solution found as an inherited
% predicate can always be re-declared
( \+ \+ PredScope = LookupScope ->
true
; Sender = SCtn
)
; fail
).
'$lgt_current_predicate'(Obj, Functor/Arity, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, _, _, Head, Ctx)
; '$lgt_use_module_predicate_'(Entity, _, _, Head, Ctx)
),
functor(Head, Functor, Arity).
% '$lgt_predicate_property'(+object_identifier, @callable, ?predicate_property, +object_identifier, +scope, @execution_context)
%
% predicate_property/2 built-in method
%
% local predicates without a scope declaration are invisible and Prolog
% built-in predicates are interpreted as private predicates
%
% the implementation ensures that no spurious choice-points are created when
% the method is called with a bound and deterministic property argument
'$lgt_predicate_property'(Obj, Pred, Prop, _, _, ExCtx) :-
'$lgt_check'(callable, Pred, logtalk(predicate_property(Pred, Prop), ExCtx)),
'$lgt_check'(var_or_predicate_property, Prop, logtalk(predicate_property(Pred, Prop), ExCtx)),
'$lgt_check'(object, Obj, logtalk(Obj::predicate_property(Pred, Prop), ExCtx)),
fail.
'$lgt_predicate_property'(user, Pred, Prop, _, _, _) :-
!,
'$lgt_predicate_property'(Pred, Prop).
'$lgt_predicate_property'(Obj, Pred, Prop, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_uses_predicate_'(Entity, Other, Original, Pred, Ctx),
!,
'$lgt_predicate_property'(Other, Original, Prop, Obj, p(p(p)), ExCtx).
'$lgt_predicate_property'(Obj, Pred, Prop, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_use_module_predicate_'(Entity, Module, Original, Pred, Ctx),
!,
'$lgt_predicate_property'(':'(Module, Original), Prop).
'$lgt_predicate_property'(Obj, Pred, Prop, Sender, LookupScope, _) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, Rnm, ObjFlags),
call(Dcl, Pred, PredScope, Meta, PredFlags, SCtn, TCtn),
% predicate declaration found
!,
( \+ \+ PredScope = LookupScope ->
true
; Sender = SCtn
),
% query is within scope
'$lgt_scope'(ScopeAsAtom, PredScope),
( '$lgt_current_object_'(TCtn, _, TCtnDcl, _, _, _, _, _, _, _, _) ->
true
; '$lgt_current_protocol_'(TCtn, _, TCtnDcl, _, _) ->
true
; '$lgt_current_category_'(TCtn, _, TCtnDcl, _, _, _)
),
( call(TCtnDcl, Pred, _, _, _) ->
% found static declaration for the predicate
'$lgt_predicate_property_user'(Prop, Pred, Pred, Obj, ScopeAsAtom, Meta, PredFlags, TCtn, Obj, Def, Rnm)
; PredFlags /\ 2 =:= 2 ->
% dynamically declared predicate; aliases can only be defined for statically declared predicates
'$lgt_predicate_property_user'(Prop, Pred, Pred, Obj, ScopeAsAtom, Meta, PredFlags, TCtn, Obj, Def, Rnm)
; % no predicate declaration; we may be querying properties of a predicate alias
'$lgt_find_original_predicate'(Obj, Rnm, ObjFlags, Pred, Original, Entity),
'$lgt_predicate_property_user'(Prop, Pred, Original, Entity, ScopeAsAtom, Meta, PredFlags, TCtn, Obj, Def, Rnm)
).
'$lgt_predicate_property'(Obj, Pred, Prop, Sender, LookupScope, _) :-
'$lgt_built_in_method'(Pred, PredScope, Meta, Flags),
!,
( \+ \+ PredScope = LookupScope ->
true
; Sender = Obj
),
'$lgt_scope'(ScopeAsAtom, PredScope),
'$lgt_predicate_property_built_in_method'(Prop, Pred, ScopeAsAtom, Meta, Flags).
'$lgt_predicate_property'(Obj, Pred, Prop, Obj, _, _) :-
'$lgt_logtalk_built_in_predicate'(Pred, Meta),
!,
'$lgt_predicate_property_logtalk_built_in'(Prop, Meta).
'$lgt_predicate_property'(Obj, Pred, Prop, Obj, _, _) :-
'$lgt_prolog_built_in_predicate'(Pred),
!,
'$lgt_predicate_property_prolog_built_in'(Prop, Pred).
'$lgt_predicate_property_user'(alias_of(Original), Alias, Original, _, _, _, _, _, _, _, _) :-
Alias \= Original.
'$lgt_predicate_property_user'(alias_declared_in(Entity), Alias, Original, Entity, _, _, _, _, _, _, _) :-
Alias \= Original.
'$lgt_predicate_property_user'(alias_declared_in(Entity, Line), Alias, Original, Entity, _, _, _, _, _, _, _) :-
Alias \= Original,
functor(Original, OriginalFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
'$lgt_entity_property_'(Entity, predicate_alias(_, OriginalFunctor/Arity, AliasFunctor/Arity, _, Line)).
'$lgt_predicate_property_user'(logtalk, _, _, _, _, _, _, _, _, _, _).
'$lgt_predicate_property_user'(scope(Scope), _, _, _, Scope, _, _, _, _, _, _).
'$lgt_predicate_property_user'((public), _, _, _, (public), _, _, _, _, _, _).
'$lgt_predicate_property_user'(protected, _, _, _, protected, _, _, _, _, _, _).
'$lgt_predicate_property_user'((private), _, _, _, (private), _, _, _, _, _, _).
'$lgt_predicate_property_user'((dynamic), _, _, _, _, _, Flags, _, _, _, _) :-
Flags /\ 2 =:= 2.
'$lgt_predicate_property_user'(static, _, _, _, _, _, Flags, _, _, _, _) :-
Flags /\ 2 =\= 2.
'$lgt_predicate_property_user'(declared_in(TCtn), _, _, _, _, _, _, TCtn, _, _, _).
'$lgt_predicate_property_user'(declared_in(TCtn, Line), _, Original, _, _, _, _, TCtn, _, _, _) :-
functor(Original, Functor, Arity),
( '$lgt_predicate_property_'(TCtn, Functor/Arity, declaration_location(Location)) ->
( Location = include(_, Line-_) ->
true
; Location = Line-_
)
; fail
).
'$lgt_predicate_property_user'(meta_predicate(Meta), Alias, _, _, _, Meta0, _, _, _, _, _) :-
Meta0 \== no,
functor(Alias, AliasFunctor, _),
Meta0 =.. [_| MetaArgs],
Meta =.. [AliasFunctor| MetaArgs].
'$lgt_predicate_property_user'(coinductive(Template), Alias, Original, _, _, _, _, TCtn, _, _, _) :-
functor(Original, Functor, Arity),
( '$lgt_predicate_property_'(TCtn, Functor/Arity, coinductive(Template0)) ->
functor(Alias, AliasFunctor, _),
Template0 =.. [_| ModeArgs],
Template =.. [AliasFunctor| ModeArgs]
; fail
).
'$lgt_predicate_property_user'((multifile), _, _, _, _, _, PredFlags, _, _, _, _) :-
PredFlags /\ 16 =:= 16.
'$lgt_predicate_property_user'(non_terminal(Functor//Arity), Alias, _, _, _, _, PredFlags, _, _, _, _) :-
PredFlags /\ 8 =:= 8,
functor(Alias, Functor, ExtArity),
Arity is ExtArity - 2.
'$lgt_predicate_property_user'(synchronized, _, _, _, _, _, PredFlags, _, _, _, _) :-
PredFlags /\ 4 =:= 4.
'$lgt_predicate_property_user'(defined_in(DCtn), Alias, _, _, _, _, _, _, _, Def, _) :-
( call(Def, Alias, _, _, _, DCtn) ->
true
; fail
).
'$lgt_predicate_property_user'(defined_in(DCtn, Line), Alias, Original, _, _, _, _, _, _, Def, _) :-
( call(Def, Alias, _, _, _, DCtn) ->
( functor(Original, Functor, Arity),
'$lgt_predicate_property_'(DCtn, Functor/Arity, flags_clauses_rules_location(_, _, _, Location)) ->
( Location = include(_, Line-_) ->
true
; Location = Line-_
)
; fail
)
; fail
).
'$lgt_predicate_property_user'(recursive, Alias, Original, _, _, _, _, _, _, Def, _) :-
( call(Def, Alias, _, _, _, DCtn) ->
( functor(Original, Functor, Arity),
'$lgt_predicate_property_'(DCtn, Functor/Arity, flags_clauses_rules_location(Flags, _, _, _)) ->
Flags /\ 8 =:= 8
; fail
)
; fail
).
'$lgt_predicate_property_user'(inline, Alias, Original, _, _, _, _, _, _, Def, _) :-
( call(Def, Alias, _, _, _, DCtn) ->
( functor(Original, Functor, Arity),
'$lgt_predicate_property_'(DCtn, Functor/Arity, flags_clauses_rules_location(Flags, _, _, _)) ->
Flags /\ 4 =:= 4
; fail
)
; fail
).
'$lgt_predicate_property_user'(redefined_from(Super), Alias, _, _, _, _, _, _, Obj, Def, _) :-
( call(Def, Alias, _, _, _, DCtn) ->
'$lgt_find_overridden_predicate'(DCtn, Obj, Alias, Super)
; fail
).
'$lgt_predicate_property_user'(redefined_from(Super, Line), Alias, Original, _, _, _, _, _, Obj, Def, _) :-
( call(Def, Alias, _, _, _, DCtn) ->
( '$lgt_find_overridden_predicate'(DCtn, Obj, Alias, Super),
functor(Original, Functor, Arity),
'$lgt_predicate_property_'(Super, Functor/Arity, flags_clauses_rules_location(_, _, _, Location)) ->
( Location = include(_, Line-_) ->
true
; Location = Line-_
)
; fail
)
; fail
).
'$lgt_predicate_property_user'(info(Info), _, Original, _, _, _, _, TCtn, _, _, _) :-
functor(Original, Functor, Arity),
( '$lgt_predicate_property_'(TCtn, Functor/Arity, info(Info)) ->
true
; fail
).
'$lgt_predicate_property_user'(mode(Mode, Solutions), Alias, Original, _, _, _, _, TCtn, _, _, _) :-
functor(Original, Functor, Arity),
% we cannot make the mode/2 property deterministic as a predicate can support several different modes
'$lgt_predicate_property_'(TCtn, Functor/Arity, mode(Mode0, Solutions)),
functor(Alias, AliasFunctor, _),
Mode0 =.. [_| ModeArgs],
Mode =.. [AliasFunctor| ModeArgs].
'$lgt_predicate_property_user'(number_of_clauses(N), Alias, Original, _, _, _, PredFlags, _, Obj, Def, _) :-
'$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 2 =:= 0,
% static object
( call(Def, Alias, _, _, _, DCtn) ->
functor(Original, Functor, Arity),
( '$lgt_predicate_property_'(DCtn, Functor/Arity, flags_clauses_rules_location(_, N0, _, _)) ->
true
; N0 is 0
),
( PredFlags /\ 16 =:= 16 ->
% multifile predicate
findall(N1, '$lgt_predicate_property_'(_, Functor/Arity, clauses_rules_location_to(N1, _, _, DCtn)), N1s),
'$lgt_sum_list'([N0| N1s], N)
; N is N0
)
; fail
).
'$lgt_predicate_property_user'(number_of_rules(N), Alias, Original, _, _, _, PredFlags, _, Obj, Def, _) :-
'$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 2 =:= 0,
% static object
( call(Def, Alias, _, _, _, DCtn) ->
functor(Original, Functor, Arity),
( '$lgt_predicate_property_'(DCtn, Functor/Arity, flags_clauses_rules_location(_, _, N0, _)) ->
true
; N0 is 0
),
( PredFlags /\ 16 =:= 16 ->
% multifile predicate
findall(N1, '$lgt_predicate_property_'(_, Functor/Arity, clauses_rules_location_to(_, N1, _, DCtn)), N1s),
'$lgt_sum_list'([N0| N1s], N)
; N is N0
)
; fail
).
'$lgt_predicate_property_built_in_method'(logtalk, _, _, _, _).
'$lgt_predicate_property_built_in_method'(scope(Scope), _, Scope, _, _).
'$lgt_predicate_property_built_in_method'((public), _, (public), _, _).
'$lgt_predicate_property_built_in_method'(protected, _, protected, _, _).
'$lgt_predicate_property_built_in_method'((private), _, (private), _, _).
'$lgt_predicate_property_built_in_method'(built_in, _, _, _, _). %Flags /\ 1 =:= 1.
'$lgt_predicate_property_built_in_method'((dynamic), _, _, _, Flags) :-
Flags /\ 2 =:= 2.
'$lgt_predicate_property_built_in_method'(static, _, _, _, Flags) :-
Flags /\ 2 =\= 2.
'$lgt_predicate_property_built_in_method'(meta_predicate(Meta), _, _, Meta, _) :-
Meta \== no.
'$lgt_predicate_property_built_in_method'((multifile), _, _, _, Flags) :-
Flags /\ 16 =:= 16.
'$lgt_predicate_property_built_in_method'(non_terminal(Functor//Arity), Pred, _, _, Flags) :-
Flags /\ 8 =:= 8,
functor(Pred, Functor, ExtArity),
Arity is ExtArity - 2.
'$lgt_predicate_property_built_in_method'(synchronized, _, _, _, Flags) :-
Flags /\ 4 =:= 4.
'$lgt_predicate_property_logtalk_built_in'(logtalk, _).
'$lgt_predicate_property_logtalk_built_in'(scope(private), _).
'$lgt_predicate_property_logtalk_built_in'((private), _).
'$lgt_predicate_property_logtalk_built_in'(built_in, _).
'$lgt_predicate_property_logtalk_built_in'(static, _).
'$lgt_predicate_property_logtalk_built_in'(meta_predicate(Meta), Meta) :-
Meta \== no.
'$lgt_predicate_property_prolog_built_in'(foreign, Pred) :-
catch('$lgt_predicate_property'(Pred, foreign), _, fail).
'$lgt_predicate_property_prolog_built_in'(prolog, Pred) :-
\+ catch('$lgt_predicate_property'(Pred, foreign), _, fail).
'$lgt_predicate_property_prolog_built_in'(scope(private), _).
'$lgt_predicate_property_prolog_built_in'((private), _).
'$lgt_predicate_property_prolog_built_in'(meta_predicate(Meta), Pred) :-
'$lgt_prolog_meta_predicate'(Pred, Meta0, _),
Meta0 =.. [_| MetaArgs0],
'$lgt_prolog_to_logtalk_meta_argument_specifiers'(MetaArgs0, MetaArgs),
Meta =.. [_| MetaArgs].
'$lgt_predicate_property_prolog_built_in'(built_in, _).
'$lgt_predicate_property_prolog_built_in'((dynamic), Pred) :-
'$lgt_predicate_property'(Pred, (dynamic)).
'$lgt_predicate_property_prolog_built_in'(static, Pred) :-
'$lgt_predicate_property'(Pred, static).
'$lgt_predicate_property_prolog_built_in'((multifile), Pred) :-
'$lgt_predicate_property'(Pred, (multifile)).
% '$lgt_scope'(?atom, ?nonvar).
%
% converts between user and internal scope representation;
% this representation was chosen as it allows testing if a scope is either
% public or protected by a single unification step with the p(_) term
'$lgt_scope'((private), p).
'$lgt_scope'(protected, p(p)).
'$lgt_scope'((public), p(p(p))).
% '$lgt_filter_scope'(@nonvar, -nonvar)
%
% filters the predicate scope;
% used in the implementation of protected-qualified relations between entities;
% public predicates become protected predicates, protected and private predicates
% are unaffected
'$lgt_filter_scope'(p(_), p(p)).
'$lgt_filter_scope'(p, p).
% '$lgt_filter_scope_container'(@nonvar, @object_identifier, @object_identifier, -object_identifier)
%
% filters the predicate scope container;
% used in the implementation of private-qualified relations between entities;
% when the predicate is public or protected, the object inheriting the predicate
% becomes the scope container; when the predicate is private, the scope container
% is the inherited scope container
'$lgt_filter_scope_container'(p(_), _, SCtn, SCtn).
'$lgt_filter_scope_container'(p, SCtn, _, SCtn).
% '$lgt_find_original_predicate'(+object_identifier, +atom, +integer, +callable, -callable, -entity_identifier)
%
% finds the predicate pointed by an alias and the entity where the alias is declared
'$lgt_find_original_predicate'(Obj, Rnm, Flags, Alias, Pred, Entity) :-
% we add a fifth argument to properly handle class hierarchies if necessary
'$lgt_find_original_predicate'(Obj, Rnm, Flags, Alias, Pred, Entity, _),
!.
'$lgt_find_original_predicate'(Obj, _, Flags, Alias, Pred, Entity, _) :-
Flags /\ 64 =:= 64, % "complements" flag set to "allow"
'$lgt_complemented_object_'(Obj, Ctg, _, _, Rnm),
'$lgt_find_original_predicate'(Ctg, Rnm, 0, Alias, Pred, Entity, _).
'$lgt_find_original_predicate'(Entity, Rnm, _, Alias, Pred, Entity, _) :-
once(call(Rnm, _, Pred, Alias)),
Pred \= Alias,
!.
'$lgt_find_original_predicate'(Obj, _, Flags, Alias, Pred, Entity, _) :-
Flags /\ 32 =:= 32, % "complements" flag set to "restrict"
'$lgt_complemented_object_'(Obj, Ctg, _, _, Rnm),
'$lgt_find_original_predicate'(Ctg, Rnm, 0, Alias, Pred, Entity, _).
'$lgt_find_original_predicate'(Obj, _, _, Alias, Pred, Entity, _) :-
'$lgt_implements_protocol_'(Obj, Ptc, _),
'$lgt_current_protocol_'(Ptc, _, _, Rnm, _),
'$lgt_find_original_predicate'(Ptc, Rnm, 0, Alias, Pred, Entity, _).
'$lgt_find_original_predicate'(Ptc, _, _, Alias, Pred, Entity, _) :-
'$lgt_extends_protocol_'(Ptc, ExtPtc, _),
'$lgt_current_protocol_'(ExtPtc, _, _, Rnm, _),
'$lgt_find_original_predicate'(ExtPtc, Rnm, 0, Alias, Pred, Entity, _).
'$lgt_find_original_predicate'(Ctg, _, _, Alias, Pred, Entity, _) :-
'$lgt_extends_category_'(Ctg, ExtCtg, _),
'$lgt_current_category_'(ExtCtg, _, _, _, Rnm, _),
'$lgt_find_original_predicate'(ExtCtg, Rnm, 0, Alias, Pred, Entity, _).
'$lgt_find_original_predicate'(Obj, _, _, Alias, Pred, Entity, _) :-
'$lgt_imports_category_'(Obj, Ctg, _),
'$lgt_current_category_'(Ctg, _, _, _, Rnm, _),
'$lgt_find_original_predicate'(Ctg, Rnm, 0, Alias, Pred, Entity, _).
'$lgt_find_original_predicate'(Obj, _, _, Alias, Pred, Entity, prototype) :-
'$lgt_extends_object_'(Obj, Parent, _),
'$lgt_current_object_'(Parent, _, _, _, _, _, _, _, _, Rnm, Flags),
'$lgt_find_original_predicate'(Parent, Rnm, Flags, Alias, Pred, Entity, prototype).
'$lgt_find_original_predicate'(Instance, _, _, Alias, Pred, Entity, instance) :-
'$lgt_instantiates_class_'(Instance, Class, _),
'$lgt_current_object_'(Class, _, _, _, _, _, _, _, _, Rnm, Flags),
'$lgt_find_original_predicate'(Class, Rnm, Flags, Alias, Pred, Entity, superclass).
'$lgt_find_original_predicate'(Class, _, _, Alias, Pred, Entity, superclass) :-
'$lgt_specializes_class_'(Class, Superclass, _),
'$lgt_current_object_'(Superclass, _, _, _, _, _, _, _, _, Rnm, Flags),
'$lgt_find_original_predicate'(Superclass, Rnm, Flags, Alias, Pred, Entity, superclass).
% '$lgt_find_overridden_predicate'(+entity_identifier, +entity_identifier, +callable, -entity_identifier)
%
% finds the entity containing the overridden predicate definition (assuming that the
% start lookup entity contains a overriding definition for the predicate)
'$lgt_find_overridden_predicate'(Obj, Self, Pred, DefCtn) :-
'$lgt_current_object_'(Obj, _, _, _, Super, _, _, _, _, _, _),
% for classes, we need to be sure we use the correct clause for "super" by looking into "self"
'$lgt_execution_context'(ExCtx, _, _, _, Self, _, _),
call(Super, Pred, ExCtx, _, _, DefCtn),
DefCtn \= Obj,
!.
'$lgt_find_overridden_predicate'(Ctg, _, Pred, DefCtn) :-
'$lgt_current_category_'(Ctg, _, _, Def, _, _),
call(Def, Pred, _, _, DefCtn),
DefCtn \= Ctg,
!.
% '$lgt_abolish'(+object_identifier, +predicate_indicator, +object_identifier, +scope, @execution_context)
%
% abolish/1 built-in method
'$lgt_abolish'(Obj, Pred, Sender, TestScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::abolish(Pred), ExCtx)),
'$lgt_check'(predicate_indicator, Pred, logtalk(abolish(Pred), ExCtx)),
'$lgt_abolish_checked'(Obj, Pred, Sender, TestScope, ExCtx).
'$lgt_abolish_checked'(user, Functor/Arity, _, _, _) :-
!,
abolish(Functor/Arity).
'$lgt_abolish_checked'(Obj, Functor/Arity, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
functor(Head, Functor, Arity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
functor(Original, OriginalFunctor, OriginalArity),
'$lgt_abolish_checked'(Other, OriginalFunctor/OriginalArity, Obj, p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
abolish(':'(Module, (Original/Arity)))
; fail
),
!.
'$lgt_abolish_checked'(Obj, Functor/Arity, Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, _, _, _, _, DDcl, DDef, _, ObjFlags),
!,
functor(Pred, Functor, Arity),
( call(Dcl, Pred, Scope, _, PredFlags) ->
% local static predicate declaration found
( (Scope = TestScope; Sender = Obj) ->
% predicate is within the scope of the sender
( PredFlags /\ 2 =:= 2 ->
% static declaration for a dynamic predicate
throw(error(permission_error(modify, predicate_declaration, Functor/Arity), logtalk(abolish(Functor/Arity), ExCtx)))
; % predicate is static
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(abolish(Functor/Arity), ExCtx)))
)
; % predicate is not within the scope of the sender
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(abolish(Functor/Arity), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(abolish(Functor/Arity), ExCtx)))
)
)
; % no static predicate declaration...
ObjFlags /\ 128 =:= 128,
% ... but dynamic declarations are allowed
DDclClause =.. [DDcl, Pred, _],
call(DDclClause) ->
% dynamic predicate declaration found
retractall(DDclClause),
DDefClause =.. [DDef, Pred, _, TPred0],
( call(DDefClause) ->
% predicate clauses exist
'$lgt_unwrap_compiled_head'(TPred0, TPred),
functor(TPred, TFunctor, TArity),
abolish(TFunctor/TArity),
retractall(DDefClause),
'$lgt_clean_lookup_caches'(Pred)
; % no predicate clauses currently exist but may have existed in the past
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
abolish(TFunctor/TArity)
)
; % no dynamic predicate declaration found
DDefClause =.. [DDef, Pred, _, TPred0],
call(DDefClause) ->
% local dynamic predicate
'$lgt_unwrap_compiled_head'(TPred0, TPred),
functor(TPred, TFunctor, TArity),
abolish(TFunctor/TArity),
retractall(DDefClause),
'$lgt_clean_lookup_caches'(Pred)
; % no predicate declaration
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(abolish(Functor/Arity), ExCtx)))
).
'$lgt_abolish_checked'(Obj, Pred, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::abolish(Pred), ExCtx))).
% '$lgt_asserta'(+object_identifier, @clause, +object_identifier, +scope, +scope, @execution_context)
%
% asserta/1 built-in method
%
% asserting facts uses a caching mechanism that saves the compiled form of the
% facts to improve performance
'$lgt_asserta'(Obj, Clause, Sender, _, _, _) :-
nonvar(Obj),
nonvar(Clause),
'$lgt_db_lookup_cache_'(Obj, Clause, Sender, TClause, _),
!,
asserta(TClause).
'$lgt_asserta'(Obj, Clause, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::asserta(Clause), ExCtx)),
'$lgt_check'(clause, Clause, logtalk(asserta(Clause), ExCtx)),
( Clause = (Head :- Body) ->
( Body == true ->
'$lgt_asserta_fact_checked'(Obj, Head, Sender, TestScope, DclScope, ExCtx)
; '$lgt_asserta_rule_checked'(Obj, Clause, Sender, TestScope, DclScope, ExCtx)
)
; '$lgt_asserta_fact_checked'(Obj, Clause, Sender, TestScope, DclScope, ExCtx)
).
'$lgt_asserta_rule_checked'(Obj, (Head:-Body), Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_asserta_rule_checked'(Other, (Original:-Body), Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
asserta(':'(Module, (Original:-Body)))
; fail
),
!.
'$lgt_asserta_rule_checked'(Obj, (Head:-Body), Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, Meta, SCtn, DclScope, asserta((Head:-Body)), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, _),
'$lgt_goal_meta_arguments'(Meta, Head, MetaArgs),
'$lgt_comp_ctx'(Ctx, Head, GExCtx, _, _, _, _, Prefix, MetaArgs, _, GExCtx, runtime, _, _, _),
'$lgt_compile_body'(Body, _, TBody, DBody, Ctx),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
asserta((THead :- ('$lgt_nop'(Body), '$lgt_debug'(rule(Obj, Head, 0, nil, 0), GExCtx), DBody)))
; asserta((THead :- ('$lgt_nop'(Body), TBody)))
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(asserta((Head:-Body)), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(asserta((Head:-Body)), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(asserta((Head:-Body)), ExCtx)))
).
'$lgt_asserta_rule_checked'(Obj, Clause, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), Obj::asserta(Clause), ExCtx)).
'$lgt_asserta_fact_checked'(Obj, Head, Sender, _, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, _),
!,
asserta(THead).
'$lgt_asserta_fact_checked'(Obj, Head, Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_asserta_fact_checked'(Other, Original, Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
asserta(':'(Module, Original))
; fail
),
!.
'$lgt_asserta_fact_checked'(Obj, Head, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, _, SCtn, DclScope, asserta(Head), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, Update),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
asserta((THead :- '$lgt_debug'(fact(Obj, Head, 0, nil, 0), GExCtx)))
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, SCtn, DclScope, Type, Sender, THead, DDef, Update),
asserta(THead)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(asserta(Head), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(asserta(Head), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(asserta(Head), ExCtx)))
).
'$lgt_asserta_fact_checked'(Obj, Head, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::asserta(Head), ExCtx))).
% '$lgt_assertz'(+object_identifier, @clause, +object_identifier, +scope, +scope, @execution_context)
%
% assertz/1 built-in method
%
% asserting facts uses a caching mechanism that saves the compiled form of the
% facts to improve performance
'$lgt_assertz'(Obj, Clause, Sender, _, _, _) :-
nonvar(Obj),
nonvar(Clause),
'$lgt_db_lookup_cache_'(Obj, Clause, Sender, TClause, _),
!,
assertz(TClause).
'$lgt_assertz'(Obj, Clause, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::assertz(Clause), ExCtx)),
'$lgt_check'(clause, Clause, logtalk(assertz(Clause), ExCtx)),
( Clause = (Head :- Body) ->
( Body == true ->
'$lgt_assertz_fact_checked'(Obj, Head, Sender, TestScope, DclScope, ExCtx)
; '$lgt_assertz_rule_checked'(Obj, Clause, Sender, TestScope, DclScope, ExCtx)
)
; '$lgt_assertz_fact_checked'(Obj, Clause, Sender, TestScope, DclScope, ExCtx)
).
'$lgt_assertz_rule_checked'(Obj, (Head:-Body), Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_assertz_rule_checked'(Other, (Original:-Body), Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
assertz(':'(Module, (Original:-Body)))
; fail
),
!.
'$lgt_assertz_rule_checked'(Obj, (Head:-Body), Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, Meta, SCtn, DclScope, assertz((Head:-Body)), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, _),
'$lgt_goal_meta_arguments'(Meta, Head, MetaArgs),
'$lgt_comp_ctx'(Ctx, Head, GExCtx, _, _, _, _, Prefix, MetaArgs, _, GExCtx, runtime, _, _, _),
'$lgt_compile_body'(Body, _, TBody, DBody, Ctx),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
assertz((THead :- ('$lgt_nop'(Body), '$lgt_debug'(rule(Obj, Head, 0, nil, 0), GExCtx), DBody)))
; assertz((THead :- ('$lgt_nop'(Body), TBody)))
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(assertz((Head:-Body)), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(assertz((Head:-Body)), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(assertz((Head:-Body)), ExCtx)))
).
'$lgt_assertz_rule_checked'(Obj, Clause, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::assertz(Clause), ExCtx))).
'$lgt_assertz_fact_checked'(Obj, Head, Sender, _, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, _),
!,
assertz(THead).
'$lgt_assertz_fact_checked'(Obj, Head, Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_assertz_fact_checked'(Other, Original, Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
assertz(':'(Module, Original))
; fail
),
!.
'$lgt_assertz_fact_checked'(Obj, Head, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, _, SCtn, DclScope, assertz(Head), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, Update),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
assertz((THead :- '$lgt_debug'(fact(Obj, Head, 0, nil, 0), GExCtx)))
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, SCtn, DclScope, Type, Sender, THead, DDef, Update),
assertz(THead)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(assertz(Head), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(assertz(Head), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(assertz(Head), ExCtx)))
).
'$lgt_assertz_fact_checked'(Obj, Head, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::assertz(Head), ExCtx))).
% gets or sets (if it doesn't exist) the declaration for an asserted predicate (but we must
% not add a scope declaration when asserting clauses for a *local* dynamic predicate)
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, ObjFlags, Pred, Scope, Type, Meta, SCtn, DclScope, Goal, ExCtx) :-
( call(Dcl, Pred, Scope, Meta, PredFlags, SCtn, _) ->
% predicate declaration found; get predicate type
( PredFlags /\ 2 =:= 2 ->
Type = (dynamic)
; Type = (static)
)
; % no predicate declaration; check for a local dynamic predicate if we're asserting locally
(DclScope == p, call(DDef, Pred, _, _)) ->
Scope = DclScope, Type = (dynamic), Meta = no, SCtn = Obj
; % not a declared predicate and not a local dynamic predicate
( DclScope == p
% object asserting a new predicate in itself
; ObjFlags /\ 128 =:= 128
% dynamic declaration of new predicates allowed
) ->
'$lgt_term_template'(Pred, DPred),
Clause =.. [DDcl, DPred, DclScope],
assertz(Clause),
Scope = DclScope, Type = (dynamic), Meta = no, SCtn = Obj
; % object doesn't allow dynamic declaration of new predicates
functor(Pred, Functor, Arity),
throw(error(permission_error(create, predicate_declaration, Functor/Arity), logtalk(Goal, ExCtx)))
).
% gets or sets (if it doesn't exist) the compiled call for an asserted predicate
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, ExCtx, THead, NeedsUpdate) :-
( call(Def, Head, ExCtx, THead0) ->
% static definition lookup entries don't require update goals
'$lgt_unwrap_compiled_head'(THead0, THead),
NeedsUpdate = false
; call(DDef, Head, ExCtx, THead0) ->
% dynamic definition lookup entries always require update goals
'$lgt_unwrap_compiled_head'(THead0, THead),
NeedsUpdate = true
; % no definition lookup entry exists; construct and assert a dynamic one
functor(Head, Functor, Arity),
functor(GHead, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(THead, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(GHead, THead, ExCtx),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
DDefClause =.. [DDef, GHead, ExCtx, '$lgt_debug'(goal(GHead,THead), ExCtx)]
; DDefClause =.. [DDef, GHead, ExCtx, THead]
),
assertz(DDefClause),
'$lgt_clean_lookup_caches'(GHead),
NeedsUpdate = true,
GHead = Head
).
% '$lgt_clause'(+object_identifier, +callable, ?callable, +object_identifier, +scope, @execution_context)
%
% clause/2 built-in method
'$lgt_clause'(Obj, Head, Body, Sender, TestScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::clause(Head, Body), ExCtx)),
'$lgt_check'(clause, (Head:-Body), logtalk(clause(Head, Body), ExCtx)),
'$lgt_clause_checked'(Obj, Head, Body, Sender, TestScope, ExCtx).
'$lgt_clause_checked'(Obj, Head, Body, Sender, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, _),
!,
clause(THead, TBody),
( TBody = ('$lgt_nop'(Body), _) ->
% rules (compiled both in normal and debug mode)
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
% facts compiled in debug mode
Body = true
; % facts compiled in normal mode
TBody = Body
).
'$lgt_clause_checked'(Obj, Head, Body, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx),
Obj \== Other,
!,
'$lgt_clause_checked'(Other, Original, Body, Obj, p(p(p)), ExCtx).
'$lgt_clause_checked'(_, Head, Body, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx),
!,
clause(':'(Module,Original), Body).
'$lgt_clause_checked'(Obj, Head, Body, Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, ObjFlags),
!,
( call(Dcl, Head, Scope, _, PredFlags, SCtn, _) ->
( (PredFlags /\ 2 =:= 2; ObjFlags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
( (call(DDef, Head, _, THead0); call(Def, Head, _, THead0)) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
clause(THead, TBody),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(clause(Head, Body), ExCtx)))
; throw(error(permission_error(access, protected_predicate, Functor/Arity), logtalk(clause(Head, Body), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(access, static_predicate, Functor/Arity), logtalk(clause(Head, Body), ExCtx)))
)
; Obj = Sender,
(call(DDef, Head, _, THead0); call(Def, Head, _, THead0)) ->
% local dynamic predicate with no scope declaration
'$lgt_unwrap_compiled_head'(THead0, THead),
clause(THead, TBody),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
)
; % unknown predicate
functor(Head, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(clause(Head, Body), ExCtx)))
).
'$lgt_clause_checked'(Obj, Head, Body, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::clause(Head, Body), ExCtx))).
% '$lgt_retract'(+object_identifier, @clause, +object_identifier, +scope, @execution_context)
%
% retract/1 built-in method
%
% the implementation must ensure that retracting the last clause for a
% predicate allows any inherited clauses to be found again as they are
% no longer being overridden
'$lgt_retract'(Obj, Clause, Sender, _, _) :-
nonvar(Obj),
nonvar(Clause),
'$lgt_db_lookup_cache_'(Obj, Clause, Sender, TClause, UpdateData),
!,
retract(TClause),
'$lgt_update_ddef_table_opt'(UpdateData).
'$lgt_retract'(Obj, Clause, Sender, TestScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::retract(Clause), ExCtx)),
'$lgt_check'(clause, Clause, logtalk(retract(Clause), ExCtx)),
( Clause = (Head :- Body) ->
( var(Body) ->
'$lgt_retract_var_body_checked'(Obj, Clause, Sender, TestScope, ExCtx)
; Body == true ->
'$lgt_retract_fact_checked'(Obj, Head, Sender, TestScope, ExCtx)
; '$lgt_retract_rule_checked'(Obj, Clause, Sender, TestScope, ExCtx)
)
; '$lgt_retract_fact_checked'(Obj, Clause, Sender, TestScope, ExCtx)
).
'$lgt_retract_var_body_checked'(Obj, (Head:-Body), Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx),
Obj \== Other,
!,
'$lgt_retract_var_body_checked'(Other, (Original:-Body), Obj, p(p(p)), ExCtx).
'$lgt_retract_var_body_checked'(_, (Head:-Body), _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx),
!,
retract((':'(Module,Original) :- Body)).
'$lgt_retract_var_body_checked'(Obj, (Head:-Body), Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, ObjFlags),
!,
( call(Dcl, Head, Scope, _, PredFlags, SCtn, _) ->
( (PredFlags /\ 2 =:= 2; ObjFlags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
( call(DDef, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
retract((THead :- TBody)),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
),
'$lgt_update_ddef_table'(DDef, Head, THead)
; call(Def, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
retract((THead :- TBody)),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
)
; Obj = Sender,
call(DDef, Head, _, THead0) ->
% local dynamic predicate with no scope declaration
'$lgt_unwrap_compiled_head'(THead0, THead),
retract((THead :- TBody)),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
)
; % unknown predicate
functor(Head, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
).
'$lgt_retract_var_body_checked'(Obj, (Head:-Body), _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::retract((Head:-Body)), ExCtx))).
'$lgt_retract_rule_checked'(Obj, (Head:-Body), Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx),
Obj \== Other,
!,
'$lgt_retract_rule_checked'(Other, (Original:-Body), Obj, p(p(p)), ExCtx).
'$lgt_retract_rule_checked'(_, (Head:-Body), _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx),
!,
retract((':'(Module,Original) :- Body)).
'$lgt_retract_rule_checked'(Obj, (Head:-Body), Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, ObjFlags),
!,
( call(Dcl, Head, Scope, _, PredFlags, SCtn, _) ->
( (PredFlags /\ 2 =:= 2; ObjFlags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
( call(DDef, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
retract((THead :- ('$lgt_nop'(Body), _))),
'$lgt_update_ddef_table'(DDef, Head, THead)
; call(Def, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
retract((THead :- ('$lgt_nop'(Body), _)))
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
)
; Obj = Sender,
call(DDef, Head, _, THead0) ->
% local dynamic predicate with no scope declaration
'$lgt_unwrap_compiled_head'(THead0, THead),
retract((THead :- ('$lgt_nop'(Body), _)))
; % unknown predicate
functor(Head, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(retract((Head:-Body)), ExCtx)))
).
'$lgt_retract_rule_checked'(Obj, (Head:-Body), _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::retract((Head:-Body)), ExCtx))).
'$lgt_retract_fact_checked'(Obj, Head, Sender, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, UpdateData),
!,
retract(THead),
'$lgt_update_ddef_table_opt'(UpdateData).
'$lgt_retract_fact_checked'(Obj, Head, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx),
Obj \== Other,
!,
'$lgt_retract_fact_checked'(Other, Original, Obj, p(p(p)), ExCtx).
'$lgt_retract_fact_checked'(_, Head, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx),
!,
retract(':'(Module,Original)).
'$lgt_retract_fact_checked'(Obj, Head, Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, ObjFlags),
!,
( call(Dcl, Head, Scope, _, PredFlags, SCtn, _) ->
( (PredFlags /\ 2 =:= 2; ObjFlags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
Type = (dynamic),
( (Scope = TestScope; Sender = SCtn) ->
( call(DDef, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
( ObjFlags /\ 512 =:= 512 ->
% object compiled in debug mode
retract((THead :- '$lgt_debug'(fact(_, _, _, _, _), _)))
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, SCtn, Scope, Type, Sender, THead, DDef, true),
retract(THead)
),
'$lgt_update_ddef_table'(DDef, Head, THead)
; call(Def, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
( ObjFlags /\ 512 =:= 512 ->
% object compiled in debug mode
retract((THead :- '$lgt_debug'(fact(_, _, _, _, _), _)))
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, Scope, Type, Sender, THead),
retract(THead)
)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(retract(Head), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(retract(Head), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(retract(Head), ExCtx)))
)
; Obj = Sender,
call(DDef, Head, _, THead0) ->
% local dynamic predicate with no scope declaration
'$lgt_unwrap_compiled_head'(THead0, THead),
( ObjFlags /\ 512 =:= 512 ->
% object compiled in debug mode
retract((THead :- '$lgt_debug'(fact(_, _, _, _, _), _)))
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, p, (dynamic), Sender, THead),
retract(THead)
)
; % unknown predicate
functor(Head, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(retract(Head), ExCtx)))
).
'$lgt_retract_fact_checked'(Obj, Head, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::retract(Head), ExCtx))).
% '$lgt_retractall'(+object_identifier, @callable, +object_identifier, +scope, @execution_context)
%
% retractall/1 built-in method
%
% the implementation must ensure that retracting the last clause for a
% predicate allows any inherited clauses to be found again as they are
% no longer being overridden
'$lgt_retractall'(Obj, Head, Sender, _, _) :-
nonvar(Obj),
nonvar(Head),
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, UpdateData),
!,
retractall(THead),
'$lgt_update_ddef_table_opt'(UpdateData).
'$lgt_retractall'(Obj, Head, Sender, TestScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::retractall(Head), ExCtx)),
'$lgt_check'(callable, Head, logtalk(retractall(Head), ExCtx)),
'$lgt_retractall_checked'(Obj, Head, Sender, TestScope, ExCtx).
'$lgt_retractall_checked'(Obj, Head, Sender, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, UpdateData),
!,
retractall(THead),
'$lgt_update_ddef_table_opt'(UpdateData).
'$lgt_retractall_checked'(Obj, Head, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_retractall_checked'(Other, Original, Obj, p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
retractall(':'(Module,Original))
; fail
),
!.
'$lgt_retractall_checked'(Obj, Head, Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, ObjFlags),
!,
( call(Dcl, Head, Scope, _, PredFlags, SCtn, _) ->
% predicate scope declaration found
( (PredFlags /\ 2 =:= 2; ObjFlags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
Type = (dynamic),
( (Scope = TestScope; Sender = SCtn) ->
( call(DDef, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
retractall(THead),
'$lgt_update_ddef_table'(DDef, Head, THead)
; call(Def, Head, _, THead0) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
( ObjFlags /\ 512 =:= 512 ->
% object compiled in debug mode
true
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, Scope, Type, Sender, THead)
),
retractall(THead)
; true
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(retractall(Head), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(retractall(Head), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(retractall(Head), ExCtx)))
)
; Obj = Sender,
call(DDef, Head, _, THead0) ->
% local dynamic predicate with no scope declaration
'$lgt_unwrap_compiled_head'(THead0, THead),
( ObjFlags /\ 512 =:= 512 ->
% object compiled in debug mode
true
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, p, (dynamic), Sender, THead)
),
retractall(THead)
; % unknown predicate
functor(Head, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(retractall(Head), ExCtx)))
).
'$lgt_retractall_checked'(Obj, Head, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::retractall(Head), ExCtx))).
% '$lgt_asserta'(+object_identifier, @clause, @term, +object_identifier, +scope, +scope, @execution_context)
%
% asserta/2 built-in method that takes a clause reference if supported
% as built-in predicates by the backend Prolog compiler
%
% asserting facts uses a caching mechanism that saves the compiled form of the
% facts to improve performance
'$lgt_asserta'(Obj, Clause, Ref, Sender, _, _, _) :-
nonvar(Obj),
nonvar(Clause),
'$lgt_db_lookup_cache_'(Obj, Clause, Sender, TClause, _),
!,
asserta(TClause, Ref).
'$lgt_asserta'(Obj, Clause, Ref, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::asserta(Clause, Ref), ExCtx)),
'$lgt_check'(clause, Clause, logtalk(asserta(Clause, Ref), ExCtx)),
( Clause = (Head :- Body) ->
( Body == true ->
'$lgt_asserta_fact_checked'(Obj, Head, Ref, Sender, TestScope, DclScope, ExCtx)
; '$lgt_asserta_rule_checked'(Obj, Clause, Ref, Sender, TestScope, DclScope, ExCtx)
)
; '$lgt_asserta_fact_checked'(Obj, Clause, Ref, Sender, TestScope, DclScope, ExCtx)
).
'$lgt_asserta_rule_checked'(Obj, (Head:-Body), Ref, Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_asserta_rule_checked'(Other, (Original:-Body), Ref, Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
asserta(':'(Module, (Original:-Body)), Ref)
; fail
),
!.
'$lgt_asserta_rule_checked'(Obj, (Head:-Body), Ref, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, Meta, SCtn, DclScope, asserta((Head:-Body), Ref), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, _),
'$lgt_goal_meta_arguments'(Meta, Head, MetaArgs),
'$lgt_comp_ctx'(Ctx, Head, GExCtx, _, _, _, _, Prefix, MetaArgs, _, GExCtx, runtime, _, _, _),
'$lgt_compile_body'(Body, _, TBody, DBody, Ctx),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
asserta((THead :- ('$lgt_nop'(Body), '$lgt_debug'(rule(Obj, Head, 0, nil, 0), GExCtx), DBody)), Ref)
; asserta((THead :- ('$lgt_nop'(Body), TBody)), Ref)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(asserta((Head:-Body), Ref), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(asserta((Head:-Body), Ref), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(asserta((Head:-Body), Ref), ExCtx)))
).
'$lgt_asserta_rule_checked'(Obj, Clause, Ref, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), Obj::asserta(Clause, Ref), ExCtx)).
'$lgt_asserta_fact_checked'(Obj, Head, Ref, Sender, _, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, _),
!,
asserta(THead, Ref).
'$lgt_asserta_fact_checked'(Obj, Head, Ref, Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_asserta_fact_checked'(Other, Original, Ref, Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
asserta(':'(Module, Original), Ref)
; fail
),
!.
'$lgt_asserta_fact_checked'(Obj, Head, Ref, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, _, SCtn, DclScope, asserta(Head, Ref), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, Update),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
asserta((THead :- '$lgt_debug'(fact(Obj, Head, 0, nil, 0), GExCtx)), Ref)
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, SCtn, DclScope, Type, Sender, THead, DDef, Update),
asserta(THead, Ref)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(asserta(Head, Ref), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(asserta(Head, Ref), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(asserta(Head, Ref), ExCtx)))
).
'$lgt_asserta_fact_checked'(Obj, Head, Ref, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::asserta(Head, Ref), ExCtx))).
% '$lgt_assertz'(+object_identifier, @clause, @term, +object_identifier, +scope, +scope, @execution_context)
%
% assertz/2 built-in method that takes a clause reference if supported
% as built-in predicates by the backend Prolog compiler
%
% asserting facts uses a caching mechanism that saves the compiled form of the
% facts to improve performance
'$lgt_assertz'(Obj, Clause, Ref, Sender, _, _, _) :-
nonvar(Obj),
nonvar(Clause),
'$lgt_db_lookup_cache_'(Obj, Clause, Sender, TClause, _),
!,
assertz(TClause, Ref).
'$lgt_assertz'(Obj, Clause, Ref, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::assertz(Clause, Ref), ExCtx)),
'$lgt_check'(clause, Clause, logtalk(assertz(Clause, Ref), ExCtx)),
( Clause = (Head :- Body) ->
( Body == true ->
'$lgt_assertz_fact_checked'(Obj, Head, Ref, Sender, TestScope, DclScope, ExCtx)
; '$lgt_assertz_rule_checked'(Obj, Clause, Ref, Sender, TestScope, DclScope, ExCtx)
)
; '$lgt_assertz_fact_checked'(Obj, Clause, Ref, Sender, TestScope, DclScope, ExCtx)
).
'$lgt_assertz_rule_checked'(Obj, (Head:-Body), Ref, Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_assertz_rule_checked'(Other, (Original:-Body), Ref, Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
assertz(':'(Module, (Original:-Body)), Ref)
; fail
),
!.
'$lgt_assertz_rule_checked'(Obj, (Head:-Body), Ref, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, Meta, SCtn, DclScope, assertz((Head:-Body), Ref), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, _),
'$lgt_goal_meta_arguments'(Meta, Head, MetaArgs),
'$lgt_comp_ctx'(Ctx, Head, GExCtx, _, _, _, _, Prefix, MetaArgs, _, GExCtx, runtime, _, _, _),
'$lgt_compile_body'(Body, _, TBody, DBody, Ctx),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
assertz((THead :- ('$lgt_nop'(Body), '$lgt_debug'(rule(Obj, Head, 0, nil, 0), GExCtx), DBody)), Ref)
; assertz((THead :- ('$lgt_nop'(Body), TBody)), Ref)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(assertz((Head:-Body), Ref), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(assertz((Head:-Body), Ref), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(assertz((Head:-Body), Ref), ExCtx)))
).
'$lgt_assertz_rule_checked'(Obj, Clause, Ref, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::assertz(Clause, Ref), ExCtx))).
'$lgt_assertz_fact_checked'(Obj, Head, Ref, Sender, _, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, _),
!,
assertz(THead, Ref).
'$lgt_assertz_fact_checked'(Obj, Head, Ref, Obj, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
( '$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx) ->
'$lgt_assertz_fact_checked'(Other, Original, Ref, Obj, p(p(_)), p(p(p)), ExCtx)
; '$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx) ->
assertz(':'(Module, Original), Ref)
; fail
),
!.
'$lgt_assertz_fact_checked'(Obj, Head, Ref, Sender, TestScope, DclScope, ExCtx) :-
'$lgt_current_object_'(Obj, Prefix, Dcl, Def, _, _, _, DDcl, DDef, _, Flags),
!,
'$lgt_assert_pred_dcl'(Obj, Dcl, DDcl, DDef, Flags, Head, Scope, Type, _, SCtn, DclScope, assertz(Head, Ref), ExCtx),
( (Type == (dynamic); Flags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
'$lgt_assert_pred_def'(Def, DDef, Flags, Prefix, Head, GExCtx, THead, Update),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
assertz((THead :- '$lgt_debug'(fact(Obj, Head, 0, nil, 0), GExCtx)), Ref)
; '$lgt_add_db_lookup_cache_entry'(Obj, Head, SCtn, DclScope, Type, Sender, THead, DDef, Update),
assertz(THead, Ref)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(modify, private_predicate, Functor/Arity), logtalk(assertz(Head, Ref), ExCtx)))
; throw(error(permission_error(modify, protected_predicate, Functor/Arity), logtalk(assertz(Head, Ref), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(modify, static_predicate, Functor/Arity), logtalk(assertz(Head, Ref), ExCtx)))
).
'$lgt_assertz_fact_checked'(Obj, Head, Ref, _, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::assertz(Head, Ref), ExCtx))).
% '$lgt_clause'(+object_identifier, +callable, ?callable, +object_identifier, +scope, @execution_context)
%
% clause/3 built-in method that takes a clause reference if supported
% as built-in predicates by the backend Prolog compiler
'$lgt_clause'(Obj, Head, Body, Ref, Sender, TestScope, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj::clause(Head, Body, Ref), ExCtx)),
( var(Ref) ->
'$lgt_check'(clause, (Head:-Body), logtalk(clause(Head, Body, Ref), ExCtx))
; '$lgt_check'(var_or_callable, Head, logtalk(clause(Head, Body, Ref), ExCtx)),
'$lgt_check'(var_or_callable, Body, logtalk(clause(Head, Body, Ref), ExCtx))
),
'$lgt_clause_checked'(Obj, Head, Body, Ref, Sender, TestScope, ExCtx).
'$lgt_clause_checked'(Obj, Head, Body, Ref, Obj, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_uses_predicate_'(Entity, Other, Original, Head, Ctx),
Obj \== Other,
!,
'$lgt_clause_checked'(Other, Original, Body, Ref, Obj, p(p(p)), ExCtx).
'$lgt_clause_checked'(_, Head, Body, Ref, _, _, ExCtx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_use_module_predicate_'(Entity, Module, Original, Head, Ctx),
!,
clause(':'(Module,Original), Body, Ref).
'$lgt_clause_checked'(Obj, Head, Body, Ref, _, _, ExCtx) :-
nonvar(Ref),
!,
clause(THead0, TBody, Ref),
'$lgt_wrap_compiled_head'(Head, THead0, ExCtx, THead),
'$lgt_current_object_'(Obj, _, _, Def, _, _, _, _, DDef, _, _),
once((call(DDef, Head, _, THead); call(Def, Head, _, THead))),
( TBody = ('$lgt_nop'(Body), _) ->
% rules (compiled both in normal and debug mode)
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
% facts compiled in debug mode
Body = true
; % facts compiled in normal mode
TBody = Body
).
'$lgt_clause_checked'(Obj, Head, Body, Ref, Sender, _, _) :-
'$lgt_db_lookup_cache_'(Obj, Head, Sender, THead, _),
!,
clause(THead, TBody, Ref),
( TBody = ('$lgt_nop'(Body), _) ->
% rules (compiled both in normal and debug mode)
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
% facts compiled in debug mode
Body = true
; % facts compiled in normal mode
TBody = Body
).
'$lgt_clause_checked'(Obj, Head, Body, Ref, Sender, TestScope, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, ObjFlags),
!,
( call(Dcl, Head, Scope, _, PredFlags, SCtn, _) ->
( (PredFlags /\ 2 =:= 2; ObjFlags /\ 2 =:= 2, Sender = SCtn) ->
% either a dynamic predicate or a dynamic object that is both the sender and the predicate scope container
( (Scope = TestScope; Sender = SCtn) ->
( (call(DDef, Head, _, THead0); call(Def, Head, _, THead0)) ->
'$lgt_unwrap_compiled_head'(THead0, THead),
clause(THead, TBody, Ref),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
)
)
; % predicate is not within the scope of the sender
functor(Head, Functor, Arity),
( Scope == p ->
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(clause(Head, Body, Ref), ExCtx)))
; throw(error(permission_error(access, protected_predicate, Functor/Arity), logtalk(clause(Head, Body, Ref), ExCtx)))
)
)
; % predicate is static
functor(Head, Functor, Arity),
throw(error(permission_error(access, static_predicate, Functor/Arity), logtalk(clause(Head, Body, Ref), ExCtx)))
)
; Obj = Sender,
(call(DDef, Head, _, THead0); call(Def, Head, _, THead0)) ->
% local dynamic predicate with no scope declaration
'$lgt_unwrap_compiled_head'(THead0, THead),
clause(THead, TBody, Ref),
( TBody = ('$lgt_nop'(Body), _) ->
true
; TBody = '$lgt_debug'(fact(_, _, _, _, _), _) ->
Body = true
; TBody = Body
)
; % unknown predicate
functor(Head, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(clause(Head, Body, Ref), ExCtx)))
).
'$lgt_clause_checked'(Obj, Head, Body, Ref, _, _, ExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::clause(Head, Body, Ref), ExCtx))).
% '$lgt_nop'(+clause)
%
% used as the first goal in the body of asserted predicate clauses that are
% rules to save the original clause body and thus support the implementation
% of the clause/2 built-in method
'$lgt_nop'(_).
% '$lgt_add_db_lookup_cache_entry'(@object_identifier, @callable, @callable, +atom, @object_identifier, @callable)
%
% adds a new database lookup cache entry (when an update goal is not required)
'$lgt_add_db_lookup_cache_entry'(Obj, Head, Scope, Type, Sender, THead) :-
'$lgt_term_template'(Obj, GObj),
'$lgt_term_template'(Head, GHead),
'$lgt_term_template'(THead, GTHead),
'$lgt_unify_head_thead_arguments'(GHead, GTHead, _),
( (Scope = p(p(p)), Type == (dynamic)) ->
asserta('$lgt_db_lookup_cache_'(GObj, GHead, _, GTHead, true))
; '$lgt_term_template'(Sender, GSender),
asserta('$lgt_db_lookup_cache_'(GObj, GHead, GSender, GTHead, true))
).
% '$lgt_add_db_lookup_cache_entry'(@object_identifier, @callable, @callable, @callable, +atom, @object_identifier, @callable, +atom, +atom)
%
% adds a new database lookup cache entry
'$lgt_add_db_lookup_cache_entry'(Obj, Head, SCtn, Scope, Type, Sender, THead, DDef, NeedsUpdate) :-
'$lgt_term_template'(Obj, GObj),
'$lgt_term_template'(Head, GHead),
'$lgt_term_template'(THead, GTHead),
'$lgt_unify_head_thead_arguments'(GHead, GTHead, _),
( NeedsUpdate == true, Sender \= SCtn ->
'$lgt_term_template'(Head, UHead),
'$lgt_term_template'(THead, UTHead),
UClause =.. [DDef, UHead, _, _],
( (Scope = p(p(p)), Type == (dynamic)) ->
asserta('$lgt_db_lookup_cache_'(GObj, GHead, _, GTHead, update(UHead, UTHead, UClause)))
; '$lgt_term_template'(Sender, GSender),
asserta('$lgt_db_lookup_cache_'(GObj, GHead, GSender, GTHead, update(UHead, UTHead, UClause)))
)
; ( (Scope = p(p(p)), Type == (dynamic)) ->
asserta('$lgt_db_lookup_cache_'(GObj, GHead, _, GTHead, true))
; '$lgt_term_template'(Sender, GSender),
asserta('$lgt_db_lookup_cache_'(GObj, GHead, GSender, GTHead, true))
)
).
% '$lgt_unify_head_thead_arguments'(+callable, +callable, @term)
%
% compiled clause heads use an extra argument for passing the execution context
'$lgt_unify_head_thead_arguments'(Head, THead, ExCtx) :-
Head =.. [_| Args],
THead =.. [_| TArgs],
'$lgt_append'(Args, [ExCtx], TArgs).
% '$lgt_phrase'(+grbody, ?list, +execution_context, +atom)
%
% phrase/2 built-in method implementation for calls where the first argument is only known at runtime
'$lgt_phrase'(GRBody, Input, ExCtx, _) :-
var(GRBody),
throw(error(instantiation_error, logtalk(phrase(GRBody, Input), ExCtx))).
'$lgt_phrase'('$lgt_local'(GRBody), Input, ExCtx, _) :-
!,
'$lgt_phrase'(GRBody, Input, ExCtx, local).
'$lgt_phrase'(GRBody, Input, ExCtx, Where) :-
'$lgt_comp_ctx_mode'(Ctx, runtime),
catch(
'$lgt_dcg_body'(GRBody, S0, S, Pred, Ctx),
Error,
throw(error(Error, logtalk(phrase(GRBody, Input), ExCtx)))
),
Input = S0, [] = S,
'$lgt_metacall'(Pred, ExCtx, Where).
% '$lgt_phrase'(+grbody, ?list, ?list, +execution_context)
%
% phrase/3 built-in method implementation for calls where the first argument is only known at runtime
'$lgt_phrase'(GRBody, Input, Rest, ExCtx, _) :-
var(GRBody),
throw(error(instantiation_error, logtalk(phrase(GRBody, Input, Rest), ExCtx))).
'$lgt_phrase'('$lgt_local'(GRBody), Input, Rest, ExCtx, _) :-
!,
'$lgt_phrase'(GRBody, Input, Rest, ExCtx, local).
'$lgt_phrase'(GRBody, Input, Rest, ExCtx, Where) :-
'$lgt_comp_ctx_mode'(Ctx, runtime),
catch(
'$lgt_dcg_body'(GRBody, S0, S, Pred, Ctx),
Error,
throw(error(Error, logtalk(phrase(GRBody, Input, Rest), ExCtx)))
),
Input = S0, Rest = S,
'$lgt_metacall'(Pred, ExCtx, Where).
% '$lgt_expand_term_local'(+object_identifier, ?term, ?term, @execution_context)
% '$lgt_expand_term_local'(+category_identifier, ?term, ?term, @execution_context)
%
% expand_term/2 local calls
%
% calls the term_expansion/2 user-defined hook predicate if defined and within scope
'$lgt_expand_term_local'(Entity, Term, Expansion, ExCtx) :-
( var(Term) ->
Expansion = Term
; '$lgt_term_expansion_local'(Entity, Term, Expand, ExCtx) ->
Expansion = Expand
; Term = (_ --> _) ->
% default grammar rule expansion
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, [], _, _, runtime, _, _, _),
catch(
'$lgt_dcg_rule'(Term, Clause, Ctx),
Error,
throw(error(Error, logtalk(expand_term(Term,_), ExCtx)))
),
( Clause = (Head :- Body),
'$lgt_compiler_flag'(optimize, on) ->
'$lgt_simplify_goal'(Body, SBody),
( SBody == true ->
Expansion = Head
; Expansion = (Head :- SBody)
)
; % fact and/or optimization disabled
Expansion = Clause
)
; Expansion = Term
).
% '$lgt_term_expansion_local'(+object_identifier, ?term, ?term, +execution_context)
%
% to avoid failures when the call is made from a multifile predicate clause,
% first the term_expansion/2 definition container is located and then the
% call is reduced to a local call
'$lgt_term_expansion_local'(Obj, Term, Expansion, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, _),
!,
( call(Dcl, term_expansion(_, _), Scope, _, _, SCtn, _) ->
( (Scope = p(_); Obj = SCtn) ->
( call(Def, term_expansion(_, _), _, _, _, DCtn) ->
( '$lgt_current_object_'(DCtn, _, _, DCtnDef, _, _, _, _, DCtnDDef, _, _) ->
( call(DCtnDef, term_expansion(Term, Expansion), ExCtx, Call) ->
true
; call(DCtnDDef, term_expansion(Term, Expansion), ExCtx, Call)
)
; '$lgt_current_category_'(DCtn, _, _, DCtnDef, _, _),
call(DCtnDef, term_expansion(Term, Expansion), ExCtx, Call)
)
; % no definition found
fail
)
; % declaration is out of scope but we can still try a local definition
call(Def, term_expansion(Term, Expansion), ExCtx, Call) ->
true
; call(DDef, term_expansion(Term, Expansion), ExCtx, Call)
)
; % no declaration for the term_expansion/2 hook predicate found;
% check for a local definition
call(Def, term_expansion(Term, Expansion), ExCtx, Call) ->
true
; call(DDef, term_expansion(Term, Expansion), ExCtx, Call)
),
!,
once(Call).
'$lgt_term_expansion_local'(Ctg, Term, Expansion, ExCtx) :-
'$lgt_current_category_'(Ctg, _, Dcl, Def, _, _),
( call(Dcl, term_expansion(_, _), Scope, _, _, DclCtn) ->
( (Scope = p(_); Ctg = DclCtn) ->
( call(Def, term_expansion(_, _), _, _, DCtn) ->
'$lgt_current_category_'(DCtn, _, _, DCtnDef, _, _),
call(DCtnDef, term_expansion(Term, Expansion), ExCtx, Call)
; % no definition found
fail
)
; % declaration is out of scope but we can still try a local definition
call(Def, term_expansion(Term, Expansion), ExCtx, Call)
)
; % no declaration for the term_expansion/2 hook predicate found;
% check for a local definition
call(Def, term_expansion(Term, Expansion), ExCtx, Call)
),
!,
once(Call).
% '$lgt_expand_term_message'(+object_identifier, ?term, ?term, +object_identifier, @scope, @execution_context)
%
% expand_term/2 messages
%
% calls the term_expansion/2 user-defined hook predicate if defined and within scope
'$lgt_expand_term_message'(Entity, Term, Expansion, Sender, Scope, ExCtx) :-
( var(Term) ->
Expansion = Term
; '$lgt_term_expansion_message'(Entity, Term, Expand, Sender, Scope) ->
Expansion = Expand
; Term = (_ --> _) ->
% default grammar rule expansion
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, [], _, _, runtime, _, _, _),
catch(
'$lgt_dcg_rule'(Term, Clause, Ctx),
Error,
throw(error(Error, logtalk(expand_term(Term,_), ExCtx)))
),
( Clause = (Head :- Body),
'$lgt_compiler_flag'(optimize, on) ->
'$lgt_simplify_goal'(Body, SBody),
( SBody == true ->
Expansion = Head
; Expansion = (Head :- SBody)
)
; % fact and/or optimization disabled
Expansion = Clause
)
; Expansion = Term
).
% '$lgt_term_expansion_message'(+object_identifier, ?term, ?term, +object_identifier, @scope)
'$lgt_term_expansion_message'(Obj, Term, Expansion, Sender, LookupScope) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, _),
( call(Dcl, term_expansion(_, _), PredScope, _, _, SCtn, _) ->
( (PredScope = LookupScope; Sender = SCtn) ->
'$lgt_execution_context'(ExCtx, Obj, Sender, Obj, Obj, [], []),
call(Def, term_expansion(Term, Expansion), ExCtx, Call, _, _)
; % message is out of scope
fail
)
; % no declaration for the term_expansion/2 hook predicate found
fail
),
!,
once(Call).
% '$lgt_expand_goal_local'(+object_identifier, ?term, ?term, @execution_context)
% '$lgt_expand_goal_local'(+category_identifier, ?term, ?term, @execution_context)
%
% expand_goal/2 local calls
%
% calls the goal_expansion/2 user-defined hook predicate if defined and within scope
'$lgt_expand_goal_local'(Obj, Goal, ExpandedGoal, ExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, DDef, _, _),
!,
( call(Dcl, goal_expansion(_, _), Scope, _, _, SCtn, _) ->
( (Scope = p(_); Obj = SCtn) ->
'$lgt_expand_goal_object_scoped'(Goal, ExpandedGoal, Def, ExCtx)
; % declaration is out of scope but we can still try a local definition
'$lgt_expand_goal_object_local'(Goal, ExpandedGoal, Def, DDef, ExCtx, [])
)
; % no declaration for the goal_expansion/2 hook predicate found;
% try to use a local definition if it exists
'$lgt_expand_goal_object_local'(Goal, ExpandedGoal, Def, DDef, ExCtx, [])
).
'$lgt_expand_goal_local'(Ctg, Goal, ExpandedGoal, ExCtx) :-
'$lgt_current_category_'(Ctg, _, Dcl, Def, _, _),
( call(Dcl, goal_expansion(_, _), Scope, _, _, DclCtn) ->
( (Scope = p(_); Ctg = DclCtn) ->
'$lgt_expand_goal_category_scoped'(Goal, ExpandedGoal, Def, ExCtx)
; % declaration is out of scope but we can still try a local definition
'$lgt_expand_goal_category_local'(Goal, ExpandedGoal, Def, ExCtx, [])
)
; % no declaration for the goal_expansion/2 hook predicate found;
% try to use a local definition if it exists
'$lgt_expand_goal_category_local'(Goal, ExpandedGoal, Def, ExCtx, [])
).
% '$lgt_expand_goal_object_scoped'(?term, ?term, +atom, +execution_context)
%
% to avoid failures when the call is made from a multifile predicate clause,
% first the goal_expansion/2 definition container is located and then the
% call is reduced to a local call
'$lgt_expand_goal_object_scoped'(Goal, ExpandedGoal, Def, ExCtx) :-
( call(Def, goal_expansion(_, _), _, _, _, DCtn) ->
( '$lgt_current_object_'(DCtn, _, _, DCtnDef, _, _, _, _, DCtnDDef, _, _) ->
'$lgt_expand_goal_object_local'(Goal, ExpandedGoal, DCtnDef, DCtnDDef, ExCtx, [])
; '$lgt_current_category_'(DCtn, _, _, DCtnDef, _, _),
'$lgt_expand_goal_category_local'(Goal, ExpandedGoal, DCtnDef, ExCtx, [])
)
; % no goal_expansion/2 hook predicate definition found
ExpandedGoal = Goal
).
% '$lgt_expand_goal_object_local'(?term, ?term, +atom, +atom, +execution_context, +list)
'$lgt_expand_goal_object_local'(Goal, ExpandedGoal, Def, DDef, ExCtx, ExpandedGoals) :-
( var(Goal) ->
ExpandedGoal = Goal
; '$lgt_push_if_new'(ExpandedGoals, Goal, NewExpandedGoals),
% lookup local goal_expansion/2 hook predicate definition
( call(Def, goal_expansion(Goal, ExpandedGoal0), ExCtx, Call)
; call(DDef, goal_expansion(Goal, ExpandedGoal0), ExCtx, Call)
) ->
( call(Call),
Goal \== ExpandedGoal0 ->
'$lgt_expand_goal_object_local'(ExpandedGoal0, ExpandedGoal, Def, DDef, ExCtx, NewExpandedGoals)
; % fixed-point found
ExpandedGoal = Goal
)
; % no local goal_expansion/2 hook predicate definition found
ExpandedGoal = Goal
).
% '$lgt_expand_goal_category_scoped'(?term, ?term, +atom, +execution_context)
%
% to avoid failures when the call is made from a multifile predicate clause,
% first the goal_expansion/2 definition container is located and then the
% call is reduced to a local call
'$lgt_expand_goal_category_scoped'(Goal, ExpandedGoal, Def, ExCtx) :-
( call(Def, goal_expansion(_, _), _, _, DCtn) ->
'$lgt_current_category_'(DCtn, _, _, DCtnDef, _, _),
'$lgt_expand_goal_category_local'(Goal, ExpandedGoal, DCtnDef, ExCtx, [])
; % no local goal_expansion/2 hook predicate definition found
ExpandedGoal = Goal
).
% '$lgt_expand_goal_object_local'(?term, ?term, +atom, +execution_context, +list)
'$lgt_expand_goal_category_local'(Goal, ExpandedGoal, Def, ExCtx, ExpandedGoals) :-
( var(Goal) ->
ExpandedGoal = Goal
; '$lgt_push_if_new'(ExpandedGoals, Goal, NewExpandedGoals),
% lookup local goal_expansion/2 hook predicate definition
call(Def, goal_expansion(Goal, ExpandedGoal0), ExCtx, Call) ->
( call(Call),
Goal \== ExpandedGoal0 ->
'$lgt_expand_goal_category_local'(ExpandedGoal0, ExpandedGoal, Def, ExCtx, NewExpandedGoals)
; % fixed-point found
ExpandedGoal = Goal
)
; % no local goal_expansion/2 hook predicate definition found
ExpandedGoal = Goal
).
% '$lgt_expand_goal_message'(+object_identifier, ?term, ?term, +object_identifier, @scope)
%
% expand_goal/2 messages
%
% calls the goal_expansion/2 user-defined hook predicate if defined and within scope
'$lgt_expand_goal_message'(Obj, Goal, ExpandedGoal, Sender, LookupScope) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, _),
( % lookup visible goal_expansion/2 hook predicate declaration
call(Dcl, goal_expansion(_, _), PredScope, _, _, SCtn, _) ->
( (PredScope = LookupScope; Sender = SCtn) ->
'$lgt_execution_context'(ExCtx, Obj, Sender, Obj, Obj, [], []),
'$lgt_expand_goal_message_aux'(Goal, ExpandedGoal, Def, ExCtx, [])
; % message is out of scope
ExpandedGoal = Goal
)
; % no declaration for the goal_expansion/2 hook predicate found
ExpandedGoal = Goal
).
% '$lgt_expand_goal_message_aux'(?term, ?term, +atom, +execution_context, +list)
'$lgt_expand_goal_message_aux'(Goal, ExpandedGoal, Def, ExCtx, ExpandedGoals) :-
( var(Goal) ->
ExpandedGoal = Goal
; '$lgt_push_if_new'(ExpandedGoals, Goal, NewExpandedGoals),
% lookup visible goal_expansion/2 hook predicate definition
call(Def, goal_expansion(Goal, ExpandedGoal0), ExCtx, Call, _, _) ->
( call(Call),
Goal \== ExpandedGoal0 ->
'$lgt_expand_goal_message_aux'(ExpandedGoal0, ExpandedGoal, Def, ExCtx, NewExpandedGoals)
; % fixed-point found
ExpandedGoal = Goal
)
; % no visible goal_expansion/2 hook predicate definition found
ExpandedGoal = Goal
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% message sending
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_send_to_self'(?term, +compilation_context)
%
% runtime processing of a message sending call when the message is not
% known at compile time
'$lgt_send_to_self'(Pred, Ctx) :-
% we must ensure that the argument is valid before compiling the message
% sending goal otherwise there would be a potential for an endless loop
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_check'(callable, Pred, logtalk(::Pred, ExCtx)),
catch('$lgt_compile_message_to_self'(Pred, TPred, Ctx), Error, throw(error(Error, logtalk(::Pred, ExCtx)))),
call(TPred).
% '$lgt_send_to_self_'(+object_identifier, +callable, +execution_context)
%
% the last clause of this dynamic binding cache predicate must always exist
% and must call the predicate that generates the missing cache entry
'$lgt_send_to_self_'(Obj, Pred, SenderExCtx) :-
'$lgt_send_to_self_nv'(Obj, Pred, SenderExCtx).
% '$lgt_send_to_self_nv'(+object_identifier, +callable, +execution_context)
%
% runtime processing of a message sending call when the arguments have already
% been type-checked; generates a cache entry to speed up future calls
'$lgt_send_to_self_nv'(Obj, Pred, SenderExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, _),
'$lgt_execution_context'(SenderExCtx, _, _, Sender, _, _, _),
( % lookup predicate declaration
call(Dcl, Pred, Scope, Meta, _, SCtn, _) ->
( % check scope
(Scope = p(_); Sender = SCtn) ->
( % construct predicate, object, and "sender" templates
'$lgt_term_template'(Pred, GPred),
'$lgt_term_template'(Obj, GObj),
'$lgt_term_template'(Sender, GSender),
% get the execution context for meta-calls
'$lgt_goal_meta_call_context'(Meta, GSenderExCtx, GSender, GMetaCallCtx),
% lookup predicate definition
'$lgt_execution_context'(GExCtx, _, GSender, GObj, GObj, GMetaCallCtx, []),
call(Def, GPred, GExCtx, GCall, _, _) ->
% cache lookup result (the cut prevents backtracking into the catchall clause)
asserta(('$lgt_send_to_self_'(GObj, GPred, GSenderExCtx) :- !, GCall)),
% unify message arguments and call method
GObj = Obj, GPred = Pred, GSender = Sender, GSenderExCtx = SenderExCtx,
call(GCall)
; % no definition found; fail as per closed-world assumption
fail
)
; % message is not within the scope of the sender
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(::Pred, SenderExCtx)))
)
; % no predicate declaration, check if it's a built-in method
'$lgt_built_in_method'(Pred, Scope, _, _) ->
( Scope == p ->
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(::Pred, SenderExCtx)))
; % Scope == p(p(p)),
'$lgt_comp_ctx'(Ctx, _, _, _, Sender, Obj, Obj, _, [], _, _, runtime, _, _, _),
'$lgt_compile_message_to_self'(Pred, Call, Ctx),
call(Call)
)
; % message not understood; check for a message forwarding handler
call(Def, forward(Pred), ExCtx, Call, _, _) ->
'$lgt_execution_context'(ExCtx, _, Sender, Obj, Obj, [], []),
call(Call)
; % give up and throw an existence error
functor(Pred, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(::Pred, SenderExCtx)))
).
% '$lgt_send_to_obj_rt'(?term, ?term, +atom, +compilation_context)
%
% runtime processing of a message sending call when the message and
% possibly the receiver object are not known at compile time
'$lgt_send_to_obj_rt'(Obj, Pred, Events, Ctx) :-
% we must ensure that the message is valid before compiling the
% message sending goal otherwise an endless loop could result
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_check'(callable, Pred, logtalk(Obj::Pred, ExCtx)),
catch(
'$lgt_compile_message_to_object'(Pred, Obj, TPred, Events, Ctx),
Error,
throw(error(Error, logtalk(Obj::Pred, ExCtx)))
),
call(TPred).
% '$lgt_send_to_obj'(+object_identifier, +callable, +execution_context)
%
% runtime processing of an event-aware message sending call when the
% receiver object is not known at compile time; as using the cache
% only requires a bound first argument, we delay errors other than an
% instantiation error for a small performance gain
'$lgt_send_to_obj'(Obj, Pred, SenderExCtx) :-
( nonvar(Obj) ->
'$lgt_send_to_obj_'(Obj, Pred, SenderExCtx)
; throw(error(instantiation_error, logtalk(Obj::Pred, SenderExCtx)))
).
% '$lgt_send_to_obj_'(+object_identifier, +callable, +execution_context)
%
% the last clause of this dynamic binding cache predicate must always exist
% and must call the predicate that generates the missing cache entry
'$lgt_send_to_obj_'(Obj, Pred, SenderExCtx) :-
'$lgt_send_to_obj_nv'(Obj, Pred, SenderExCtx).
% '$lgt_send_to_obj_nv'(+object_identifier, +callable, +execution_context)
%
% runtime processing of an event-aware message sending call when the arguments
% have already been type-checked; generates a cache entry to speed up future calls
'$lgt_send_to_obj_nv'(Obj, Pred, SenderExCtx) :-
'$lgt_execution_context'(SenderExCtx, _, _, Sender, _, _, _),
% call all before event handlers
\+ ('$lgt_before_event_'(Obj, Pred, Sender, _, Before), \+ Before),
% process the message; we cannot simply call '$lgt_send_to_obj_ne'/3
% as the generated cache entries are different
'$lgt_send_to_obj_nv_inner'(Obj, Pred, Sender, SenderExCtx),
% call all after event handlers
\+ ('$lgt_after_event_'(Obj, Pred, Sender, _, After), \+ After).
'$lgt_send_to_obj_nv_inner'(Obj, Pred, Sender, SenderExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, _),
!,
( % lookup predicate declaration
call(Dcl, Pred, Scope, Meta, _, SCtn, _) ->
( % check public scope
Scope = p(p(_)) ->
( % construct predicate and object templates
'$lgt_term_template'(Pred, GPred),
'$lgt_term_template'(Obj, GObj),
% get the execution context for meta-calls
'$lgt_goal_meta_call_context'(Meta, GSenderExCtx, GSender, GMetaCallCtx),
% lookup predicate definition
'$lgt_execution_context'(GExCtx, _, GSender, GObj, GObj, GMetaCallCtx, []),
call(Def, GPred, GExCtx, GCall, _, _) ->
GGCall = '$lgt_guarded_method_call'(GObj, GPred, GSender, GCall),
% cache lookup result (the cut prevents backtracking into the catchall clause)
asserta(('$lgt_send_to_obj_'(GObj, GPred, GSenderExCtx) :- !, GGCall)),
% unify message arguments and call method
GObj = Obj, GPred = Pred, GSender = Sender, GSenderExCtx = SenderExCtx,
call(GCall)
; % no definition found; fail as per closed-world assumption
fail
)
; % protected or private scope: check if sender and scope container are the same;
% do not cache the lookup result as it's only valid when the sender unifies with
% the scope container
Sender = SCtn ->
( '$lgt_execution_context'(ExCtx, _, Sender, Obj, Obj, _, []),
% lookup predicate definition
call(Def, Pred, ExCtx, Call, _, _) ->
'$lgt_guarded_method_call'(Obj, Pred, Sender, Call)
; % no definition found; fail as per closed-world assumption
fail
)
; % message is not within the scope of the sender
functor(Pred, Functor, Arity),
( Scope == p ->
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
; throw(error(permission_error(access, protected_predicate, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
)
)
; % no predicate declaration, check if it's a built-in method
'$lgt_built_in_method'(Pred, Scope, _, _) ->
( Scope == p ->
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
; % Scope == p(p(p)),
'$lgt_comp_ctx'(Ctx, _, _, _, Sender, Obj, Obj, _, _, _, _, runtime, _, _, _),
'$lgt_compile_message_to_object'(Pred, Obj, Call, allow, Ctx),
call(Call)
)
; % message not understood; check for a message forwarding handler
call(Def, forward(Pred), ExCtx, Call, _, _) ->
'$lgt_execution_context'(ExCtx, _, Sender, Obj, Obj, [], []),
call(Call)
; % give up and throw an existence error
functor(Pred, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
).
'$lgt_send_to_obj_nv_inner'({Proxy}, Pred, _, SenderExCtx) :-
!,
% parametric object proxy
catch(Proxy, error(Error, _), throw(error(Error, logtalk({Proxy}::Pred, SenderExCtx)))),
'$lgt_send_to_obj_'(Proxy, Pred, SenderExCtx).
'$lgt_send_to_obj_nv_inner'(Obj, Pred, _, _) :-
atom(Obj),
'$lgt_prolog_feature'(modules, supported),
current_module(Obj),
!,
% allow Obj::Pred to be used as a shortcut for calling module predicates
':'(Obj, Pred).
'$lgt_send_to_obj_nv_inner'(Obj, Pred, _, SenderExCtx) :-
\+ callable(Obj),
throw(error(type_error(object_identifier, Obj), logtalk(Obj::Pred, SenderExCtx))).
'$lgt_send_to_obj_nv_inner'(Obj, Pred, _, SenderExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::Pred, SenderExCtx))).
% '$lgt_guarded_method_call'(+object_identifier, +callable, +object_identifier, +callable)
%
% wraps the method call with the before and after event handler calls; the "before" event handler
% may prevent a method from being executed by failing and an "after" event handler may prevent a
% method from succeeding by failing; however, event handlers cannot modify the method call
'$lgt_guarded_method_call'(Obj, Msg, Sender, Method) :-
% call before event handlers
\+ ('$lgt_before_event_'(Obj, Msg, Sender, _, Before), \+ Before),
% call method
call(Method),
% call after event handlers
\+ ('$lgt_after_event_'(Obj, Msg, Sender, _, After), \+ After).
% '$lgt_send_to_obj_ne'(+object_identifier, +callable, +execution_context)
%
% runtime processing of an event-transparent message sending call when
% the receiver object is not known at compile time; as using the cache
% only requires a bound first argument, we delay errors other than an
% instantiation error for a small performance gain
'$lgt_send_to_obj_ne'(Obj, Pred, SenderExCtx) :-
( nonvar(Obj) ->
'$lgt_send_to_obj_ne_'(Obj, Pred, SenderExCtx)
; throw(error(instantiation_error, logtalk(Obj::Pred, SenderExCtx)))
).
% '$lgt_send_to_obj_ne_'(+object_identifier, +callable, +execution_context)
%
% the last clause of this dynamic binding cache predicate must always exist
% and must call the predicate that generates the missing cache entry
'$lgt_send_to_obj_ne_'(Obj, Pred, SenderExCtx) :-
'$lgt_send_to_obj_ne_nv'(Obj, Pred, SenderExCtx).
% '$lgt_send_to_obj_ne_nv'(+object_identifier, +term, +execution_context)
%
% runtime processing of an event-transparent message sending call when the arguments
% have already been type-checked; generates a cache entry to speed up future calls
'$lgt_send_to_obj_ne_nv'(Obj, Pred, SenderExCtx) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, _),
!,
'$lgt_execution_context'(SenderExCtx, _, _, Sender, _, _, _),
( % lookup predicate declaration
call(Dcl, Pred, Scope, Meta, _, SCtn, _) ->
( % check public scope
Scope = p(p(_)) ->
( % construct predicate and object templates
'$lgt_term_template'(Pred, GPred),
'$lgt_term_template'(Obj, GObj),
% get the execution context for meta-calls
'$lgt_goal_meta_call_context'(Meta, GSenderExCtx, GSender, GMetaCallCtx),
% lookup predicate definition
'$lgt_execution_context'(GExCtx, _, GSender, GObj, GObj, GMetaCallCtx, []),
call(Def, GPred, GExCtx, GCall, _, _) ->
% cache lookup result (the cut prevents backtracking into the catchall clause)
asserta(('$lgt_send_to_obj_ne_'(GObj, GPred, GSenderExCtx) :- !, GCall)),
% unify message arguments and call method
GObj = Obj, GPred = Pred, GSender = Sender, GSenderExCtx = SenderExCtx,
call(GCall)
; % no definition found; fail as per closed-world assumption
fail
)
; % protected or private scope: check if sender and scope container are the same;
% do not cache the lookup result as it's only valid when the sender unifies with
% the scope container
Sender = SCtn ->
( % lookup predicate definition
'$lgt_execution_context'(ExCtx, _, Sender, Obj, Obj, _, []),
call(Def, Pred, ExCtx, Call, _, _) ->
call(Call)
; % no definition found; fail as per closed-world assumption
fail
)
; % message is not within the scope of the sender
functor(Pred, Functor, Arity),
( Scope == p ->
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
; throw(error(permission_error(access, protected_predicate, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
)
)
; % no predicate declaration, check if it's a built-in method
'$lgt_built_in_method'(Pred, Scope, _, _) ->
( Scope == p ->
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
; % Scope == p(p(p)),
'$lgt_comp_ctx'(Ctx, _, _, _, Sender, Obj, Obj, _, _, _, _, runtime, _, _, _),
'$lgt_compile_message_to_object'(Pred, Obj, Call, deny, Ctx),
call(Call)
)
; % message not understood; check for a message forwarding handler
call(Def, forward(Pred), ExCtx, Call, _, _) ->
'$lgt_execution_context'(ExCtx, _, Sender, Obj, Obj, [], []),
call(Call)
; % give up and throw an existence error
functor(Pred, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(Obj::Pred, SenderExCtx)))
).
'$lgt_send_to_obj_ne_nv'({Proxy}, Pred, SenderExCtx) :-
!,
% parametric object proxy
catch(Proxy, error(Error, _), throw(error(Error, logtalk({Proxy}::Pred, SenderExCtx)))),
'$lgt_send_to_obj_ne_'(Proxy, Pred, SenderExCtx).
'$lgt_send_to_obj_ne_nv'(Obj, Pred, _) :-
atom(Obj),
'$lgt_prolog_feature'(modules, supported),
current_module(Obj),
!,
% allow Obj::Pred to be used as a shortcut for calling module predicates
':'(Obj, Pred).
'$lgt_send_to_obj_ne_nv'(Obj, Pred, SenderExCtx) :-
\+ callable(Obj),
throw(error(type_error(object_identifier, Obj), logtalk(Obj::Pred, SenderExCtx))).
'$lgt_send_to_obj_ne_nv'(Obj, Pred, SenderExCtx) :-
throw(error(existence_error(object, Obj), logtalk(Obj::Pred, SenderExCtx))).
% '$lgt_obj_super_call'(+atom, +term, +execution_context)
%
% runtime processing of an object "super" call when the predicate called is
% not known at compile time; as using the cache only requires a bound first
% argument, we delay errors other than an instantiation error for a small
% performance gain
'$lgt_obj_super_call'(Super, Pred, ExCtx) :-
( nonvar(Pred) ->
'$lgt_obj_super_call_'(Super, Pred, ExCtx)
; throw(error(instantiation_error, logtalk(^^Pred, ExCtx)))
).
% '$lgt_obj_super_call_'(+atom, +callable, +execution_context)
%
% the last clause of this dynamic binding cache predicate must always exist
% and must call the predicate that generates the missing cache entry
'$lgt_obj_super_call_'(Super, Pred, ExCtx) :-
'$lgt_obj_super_call_nv'(Super, Pred, ExCtx).
% '$lgt_obj_super_call_nv'(+atom, +callable, +execution_context)
%
% runtime processing of an object "super" call when the arguments have already
% been type-checked; generates a cache entry to speed up future calls
%
% we may need to pass "self" when looking for the inherited predicate definition
% in order to be able to select the correct "super" clause for those cases where
% "this" both instantiates and specializes other objects
'$lgt_obj_super_call_nv'(Super, Pred, ExCtx) :-
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(Self, _, Dcl, _, _, _, _, _, _, _, _),
( % lookup predicate declaration (the predicate must not be
% declared in the same entity making the "super" call)
call(Dcl, Pred, Scope, _, _, SCtn, TCtn), TCtn \= This ->
( % check scope
(Scope = p(_); This = SCtn) ->
( % construct predicate, "this", and "self" templates
'$lgt_term_template'(Pred, GPred),
'$lgt_term_template'(This, GThis),
'$lgt_term_template'(Self, GSelf),
% check if we have a dependency on "self" to select the correct "super" clause
( '$lgt_extends_object_'(GThis, _, _) ->
true
; '$lgt_execution_context'(GExCtx, _, _, GThis, GSelf, _, _)
),
% lookup predicate definition (the predicate must not be
% defined in the same entity making the "super" call)
call(Super, GPred, GExCtx, GCall, _, DefCtn), DefCtn \= GThis ->
% cache lookup result (the cut prevents backtracking into the catchall clause)
asserta(('$lgt_obj_super_call_'(Super, GPred, GExCtx) :- !, GCall)),
% unify message arguments and call inherited definition
GPred = Pred, GExCtx = ExCtx,
call(GCall)
; % no definition found; fail as per closed-world assumption
fail
)
; % predicate is not within the scope of the sender
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(^^Pred, ExCtx)))
)
; % no predicate declaration, check if it's a private built-in method
'$lgt_built_in_method'(Pred, p, _, _) ->
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(^^Pred, ExCtx)))
; % non-callable term error
\+ callable(Pred) ->
throw(error(type_error(callable, Pred), logtalk(^^Pred, ExCtx)))
; % give up and throw an existence error
functor(Pred, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(^^Pred, ExCtx)))
).
% '$lgt_ctg_super_call'(+category_identifier, +term, +execution_context)
%
% runtime processing of a category "super" call when the predicate called
% is not known at compile time; as using the cache only requires a bound
% first argument, we delay errors other than an instantiation error for a
% small performance gain
'$lgt_ctg_super_call'(Ctg, Pred, ExCtx) :-
( nonvar(Pred) ->
'$lgt_ctg_super_call_'(Ctg, Pred, ExCtx)
; throw(error(instantiation_error, logtalk(^^Pred, ExCtx)))
).
% '$lgt_ctg_super_call_'(+category_identifier, +callable, +execution_context)
%
% the last clause of this dynamic binding cache predicate must always exist
% and must call the predicate that generates the missing cache entry
'$lgt_ctg_super_call_'(Ctg, Pred, ExCtx) :-
'$lgt_ctg_super_call_nv'(Ctg, Pred, ExCtx).
% '$lgt_ctg_super_call_nv'(+category_identifier, +callable, +execution_context)
%
% runtime processing of a category "super" call when the arguments have already
% been type-checked; generates a cache entry to speed up future calls
'$lgt_ctg_super_call_nv'(Ctg, Pred, ExCtx) :-
'$lgt_current_category_'(Ctg, _, Dcl, Def, _, _),
( % lookup predicate declaration (the predicate must not be
% declared in the same entity making the "super" call)
call(Dcl, Pred, Scope, _, _, DclCtn), DclCtn \= Ctg ->
( % check that the call is within scope (i.e. public or protected)
Scope = p(_) ->
( % construct category and predicate templates
'$lgt_term_template'(Ctg, GCtg),
'$lgt_term_template'(Pred, GPred),
% lookup predicate definition (the predicate must not be
% defined in the same entity making the "super" call)
call(Def, GPred, GExCtx, GCall, DefCtn), DefCtn \= Ctg ->
% cache lookup result (the cut prevents backtracking into the catchall clause)
asserta(('$lgt_ctg_super_call_'(GCtg, GPred, GExCtx) :- !, GCall)),
% unify message arguments and call inherited definition
GCtg = Ctg, GPred = Pred, GExCtx = ExCtx,
call(GCall)
; % no definition found; fail as per closed-world assumption
fail
)
; % predicate is not within the scope of the sender
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(^^Pred, ExCtx)))
)
; % no predicate declaration, check if it's a private built-in method
'$lgt_built_in_method'(Pred, p, _, _) ->
functor(Pred, Functor, Arity),
throw(error(permission_error(access, private_predicate, Functor/Arity), logtalk(^^Pred, ExCtx)))
; % non-callable term error
\+ callable(Pred) ->
throw(error(type_error(callable, Pred), logtalk(^^Pred, ExCtx)))
; % give up and throw an existence error
functor(Pred, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(^^Pred, ExCtx)))
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% meta-calls
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_lambda'(+curly_bracketed_term, @callable)
%
% calls a lambda-call with free variables but no parameters (Free/Goal) where the
% arguments are already checked and compiled; typically used in bagof/3 and setof/3
% as an alternative to the enumeration of all existentially quantified variables
'$lgt_lambda'(Free, Goal) :-
'$lgt_copy_term_without_constraints'(Free/Goal, Free/GoalCopy),
call(GoalCopy).
% '$lgt_metacall'(?term, +list, +execution_context, +atom)
%
% performs a runtime meta-call constructed from a closure and a list
% of additional arguments
%
% the last argument is either "local", in case of a local meta-call,
% or "runtime", in case the decision between a local meta-call or a
% meta-call in the sender is decided at runtime
'$lgt_metacall'(Closure, ExtraArgs, ExCtx, _) :-
var(Closure),
Call =.. [call, Closure| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx))).
'$lgt_metacall'('$lgt_closure'(TFunctor, TArgs, ExCtx), ExtraArgs, _, _) :-
% pre-compiled closure (note that the closure may be called from a mapping
% predicate, which prevents us to use a difference list based solution to
% avoid the calls to append/3 and =../2 as that would fix the extra arguments
% in the goal on the first closure call and thus break the followup calls)
!,
'$lgt_append'(TArgs, ExtraArgs, FullArgs),
TGoal =.. [TFunctor| FullArgs],
call(TGoal, ExCtx).
'$lgt_metacall'('$lgt_local'(Closure), ExtraArgs, ExCtx, _) :-
!,
'$lgt_metacall'(Closure, ExtraArgs, ExCtx, local).
'$lgt_metacall'({Closure}, ExtraArgs, ExCtx, _) :-
!,
% compiler bypass (call of external code)
( atom(Closure) ->
Goal =.. [Closure| ExtraArgs],
call(Goal)
; compound(Closure) ->
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
call(Goal)
; var(Closure) ->
Call =.. [call, {Closure}| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; Call =.. [call, {Closure}| ExtraArgs],
throw(error(type_error(callable, Closure), logtalk(Call, ExCtx)))
).
'$lgt_metacall'(::Closure, ExtraArgs, ExCtx, Where) :-
!,
'$lgt_execution_context'(ExCtx, _, _, _, Self0, CallerExCtx, _),
( CallerExCtx == [] ->
Self = Self0,
SelfExCtx = ExCtx
; Where == (local) ->
Self = Self0,
SelfExCtx = ExCtx
; '$lgt_execution_context'(CallerExCtx, _, _, _, Self, _, _),
SelfExCtx = CallerExCtx
),
( atom(Closure) ->
Goal =.. [Closure| ExtraArgs],
'$lgt_send_to_self_'(Self, Goal, SelfExCtx)
; compound(Closure) ->
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
'$lgt_send_to_self_'(Self, Goal, SelfExCtx)
; var(Closure) ->
Call =.. [call, ::Closure| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; Call =.. [call, ::Closure| ExtraArgs],
throw(error(type_error(callable, ::Closure), logtalk(Call, ExCtx)))
).
'$lgt_metacall'(^^Closure, ExtraArgs, ExCtx, Where) :-
!,
'$lgt_execution_context'(ExCtx, Entity0, _, _, _, CallerExCtx, _),
( CallerExCtx == [] ->
Entity = Entity0,
SuperExCtx = ExCtx
; Where == (local) ->
Entity = Entity0,
SuperExCtx = ExCtx
; '$lgt_execution_context'(CallerExCtx, Entity, _, _, _, _, _),
SuperExCtx = CallerExCtx
),
( atom(Closure) ->
Goal =.. [Closure| ExtraArgs]
; compound(Closure) ->
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs]
; var(Closure) ->
Call =.. [call, ^^Closure| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; Call =.. [call, ^^Closure| ExtraArgs],
throw(error(type_error(callable, Closure), logtalk(Call, ExCtx)))
),
( '$lgt_current_object_'(Entity, _, _, _, Super, _, _, _, _, _, _) ->
'$lgt_obj_super_call_'(Super, Goal, SuperExCtx)
; '$lgt_current_category_'(Entity, _, _, _, _, _),
'$lgt_ctg_super_call_'(Entity, Goal, SuperExCtx)
).
'$lgt_metacall'(Obj::Closure, ExtraArgs, ExCtx, Where) :-
!,
'$lgt_execution_context'(ExCtx, _, Sender0, This, _, CallerExCtx0, _),
( CallerExCtx0 == [] ->
CallerExCtx = ExCtx,
Sender = This
; Where == (local) ->
CallerExCtx = ExCtx,
Sender = This
; CallerExCtx = CallerExCtx0,
Sender = Sender0
),
( callable(Obj), callable(Closure) ->
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
( '$lgt_current_object_'(Sender, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 16 =:= 16 ->
'$lgt_send_to_obj_'(Obj, Goal, CallerExCtx)
; '$lgt_send_to_obj_ne_'(Obj, Goal, CallerExCtx)
)
; var(Obj) ->
Call =.. [call, Obj::Closure| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; var(Closure) ->
Call =.. [call, Obj::Closure| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; \+ callable(Closure) ->
Call =.. [call, Obj::Closure| ExtraArgs],
throw(error(type_error(callable, Closure), logtalk(Call, ExCtx)))
; Call =.. [call, Obj::Closure| ExtraArgs],
throw(error(type_error(object_identifier, Obj), logtalk(Call, ExCtx)))
).
'$lgt_metacall'([Obj::Closure], ExtraArgs, ExCtx, Where) :-
!,
'$lgt_execution_context'(ExCtx, _, Sender0, _, _, CallerExCtx0, _),
( CallerExCtx0 == [] ->
CallerExCtx1 = ExCtx,
Sender = Sender0
; Where == (local) ->
CallerExCtx1 = ExCtx,
Sender = Sender0
; '$lgt_execution_context'(CallerExCtx0, _, Sender, _, _, _, _),
CallerExCtx1 = CallerExCtx0
),
( callable(Obj), callable(Closure), Obj \= Sender ->
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
% prevent the original sender, which is preserved when delegating a message, to be reset to "this"
'$lgt_execution_context'(CallerExCtx1, Entity, Sender, _, Self, MetaCallCtx, Stack),
'$lgt_execution_context'(CallerExCtx, Entity, Sender, Sender, Self, MetaCallCtx, Stack),
( '$lgt_current_object_'(Sender, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 16 =:= 16 ->
'$lgt_send_to_obj_'(Obj, Goal, CallerExCtx)
; '$lgt_send_to_obj_ne_'(Obj, Goal, CallerExCtx)
)
; var(Obj) ->
Call =.. [call, [Obj::Closure]| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; var(Closure) ->
Call =.. [call, [Obj::Closure]| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; \+ callable(Closure) ->
Call =.. [call, [Obj::Closure]| ExtraArgs],
throw(error(type_error(callable, Closure), logtalk(Call, ExCtx)))
; \+ callable(Obj) ->
Call =.. [call, [Obj::Closure]| ExtraArgs],
throw(error(type_error(object_identifier, Obj), logtalk(Call, ExCtx)))
; % Obj = Sender ->
Call =.. [call, [Obj::Closure]| ExtraArgs],
throw(error(permission_error(access, object, Sender), logtalk(Call, ExCtx)))
).
'$lgt_metacall'(Obj<
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
'$lgt_call_within_context_nv'(Obj, Goal, ExCtx)
; var(Obj) ->
Call =.. [call, Obj<
Call =.. [call, Obj<
Call =.. [call, Obj<
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
':'(Module, Goal)
; var(Module) ->
Call =.. [call, ':'(Module, Closure)| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; var(Closure) ->
Call =.. [call, ':'(Module, Closure)| ExtraArgs],
throw(error(instantiation_error, logtalk(Call, ExCtx)))
; \+ atom(Module) ->
Call =.. [call, ':'(Module, Closure)| ExtraArgs],
throw(error(type_error(module_identifier, Module), logtalk(Call, ExCtx)))
; Call =.. [call, ':'(Module, Closure)| ExtraArgs],
throw(error(type_error(callable, Closure), logtalk(Call, ExCtx)))
).
'$lgt_metacall'(Free/Lambda, ExtraArgs, ExCtx, Where) :-
!,
'$lgt_check'(curly_bracketed_term, Free, logtalk(Free/Lambda, ExCtx)),
'$lgt_execution_context'(ExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack),
'$lgt_copy_term_without_constraints'(Free/Lambda+MetaCallCtx, Free/LambdaCopy+MetaCallCtxCopy),
'$lgt_execution_context'(NewExCtx, Entity, Sender, This, Self, MetaCallCtxCopy, Stack),
'$lgt_metacall'(LambdaCopy, ExtraArgs, NewExCtx, Where).
'$lgt_metacall'(Free/Parameters>>Lambda, ExtraArgs, ExCtx, Where) :-
!,
'$lgt_check'(curly_bracketed_term, Free, logtalk(Free/Parameters>>Lambda, ExCtx)),
'$lgt_execution_context'(ExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack),
'$lgt_copy_term_without_constraints'(Free/Parameters>>Lambda+MetaCallCtx, Free/ParametersCopy>>LambdaCopy+MetaCallCtxCopy),
'$lgt_unify_lambda_parameters'(ParametersCopy, ExtraArgs, Rest, Free/Parameters>>Lambda, This),
'$lgt_execution_context'(NewExCtx, Entity, Sender, This, Self, MetaCallCtxCopy, Stack),
'$lgt_metacall'(LambdaCopy, Rest, NewExCtx, Where).
'$lgt_metacall'(Parameters>>Lambda, ExtraArgs, ExCtx, Where) :-
!,
'$lgt_execution_context'(ExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack),
'$lgt_copy_term_without_constraints'(Parameters>>Lambda+MetaCallCtx, ParametersCopy>>LambdaCopy+MetaCallCtxCopy),
'$lgt_unify_lambda_parameters'(ParametersCopy, ExtraArgs, Rest, Parameters>>Lambda, ExCtx),
'$lgt_execution_context'(NewExCtx, Entity, Sender, This, Self, MetaCallCtxCopy, Stack),
'$lgt_metacall'(LambdaCopy, Rest, NewExCtx, Where).
'$lgt_metacall'(Closure, ExtraArgs, ExCtx, Where) :-
( atom(Closure) ->
Goal =.. [Closure| ExtraArgs]
; compound(Closure) ->
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs]
; Call =.. [call, Closure| ExtraArgs],
throw(error(type_error(callable, Closure), logtalk(Call, ExCtx)))
),
'$lgt_execution_context'(ExCtx, _, _, _, _, CallerExCtx, _),
( CallerExCtx == [] ->
'$lgt_metacall_local'(Goal, ExCtx)
; Where == (local) ->
'$lgt_metacall_local'(Goal, ExCtx)
; '$lgt_metacall_sender'(Goal, ExCtx, CallerExCtx, ExtraArgs)
).
'$lgt_unify_lambda_parameters'((-), _, _, Lambda, ExCtx) :-
% catch variables and lists with unbound tails
( Lambda = _/Parameters>>_
; Lambda = Parameters>>_
),
throw(error(type_error(list, Parameters), logtalk(Lambda, ExCtx))).
'$lgt_unify_lambda_parameters'([], ExtraArguments, ExtraArguments, _, _) :-
!.
'$lgt_unify_lambda_parameters'([Parameter| Parameters], [Argument| Arguments], ExtraArguments, Lambda, ExCtx) :-
!,
Parameter = Argument,
'$lgt_unify_lambda_parameters'(Parameters, Arguments, ExtraArguments, Lambda, ExCtx).
'$lgt_unify_lambda_parameters'(_, _, _, Lambda, ExCtx) :-
throw(error(representation_error(lambda_parameters), logtalk(Lambda, ExCtx))).
% '$lgt_metacall'(?term, +execution_context, +atom)
%
% performs a meta-call at runtime
%
% the last argument is either "local", in case of a local meta-call,
% or "runtime", in case the decision between a local meta-call or a
% meta-call in the sender is decided at runtime
'$lgt_metacall'(Goal, ExCtx, _) :-
var(Goal),
throw(error(instantiation_error, logtalk(call(Goal), ExCtx))).
'$lgt_metacall'('$lgt_local'(Goal), ExCtx, _) :-
!,
'$lgt_metacall'(Goal, ExCtx, local).
'$lgt_metacall'({Goal}, ExCtx, _) :-
% pre-compiled meta-calls or calls in "user" (compiler bypass)
!,
( callable(Goal) ->
call(Goal)
; var(Goal) ->
throw(error(instantiation_error, logtalk({Goal}, ExCtx)))
; throw(error(type_error(callable, Goal), logtalk({Goal}, ExCtx)))
).
'$lgt_metacall'(Goal, ExCtx, Where) :-
'$lgt_execution_context'(ExCtx, _, _, _, _, CallerExCtx, _),
( CallerExCtx == [] ->
'$lgt_metacall_local'(Goal, ExCtx)
; Where == (local) ->
'$lgt_metacall_local'(Goal, ExCtx)
; '$lgt_metacall_sender'(Goal, ExCtx, CallerExCtx, [])
).
% '$lgt_quantified_metacall'(?term, +execution_context, +atom)
%
% performs a possibly qualified meta-call at runtime for goals within bagof/3 and setof/3 calls
%
% the first argument is the original goal in the bagof/3 or setof/3 call and it's used to check
% in which context the meta-call should take place
%
% the second argument is the original goal without existential variables that will be meta-called
'$lgt_quantified_metacall'(Goal, ExCtx, _) :-
var(Goal),
throw(error(instantiation_error, logtalk(call(Goal), ExCtx))).
'$lgt_quantified_metacall'('$lgt_local'(Goal), ExCtx, _) :-
!,
'$lgt_quantified_metacall'(Goal, ExCtx, local).
'$lgt_quantified_metacall'({Goal}, ExCtx, _) :-
% pre-compiled meta-calls or calls in "user" (compiler bypass)
!,
( callable(Goal) ->
call(Goal)
; var(Goal) ->
throw(error(instantiation_error, logtalk({Goal}, ExCtx)))
; throw(error(type_error(callable, Goal), logtalk({Goal}, ExCtx)))
).
'$lgt_quantified_metacall'(Goal, ExCtx, Where) :-
'$lgt_execution_context'(ExCtx, _, _, _, _, CallerExCtx, _),
( CallerExCtx == [] ->
'$lgt_metacall_local'(Goal, ExCtx)
; Where == (local) ->
'$lgt_metacall_local'(Goal, ExCtx)
; '$lgt_metacall_sender'(Goal, ExCtx, CallerExCtx, [])
).
% '$lgt_metacall_local'(+callable, +execution_context)
%
% performs a local meta-call at runtime
'$lgt_metacall_local'(Pred, ExCtx) :-
'$lgt_execution_context'(ExCtx, Entity, Sender, This, Self, _, Stack),
( '$lgt_current_object_'(Entity, Prefix, _, Def, _, _, _, _, DDef, _, Flags) ->
( % in the most common case we're meta-calling a user defined static predicate
call(Def, Pred, ExCtx, TPred) ->
call(TPred)
; % or a user defined dynamic predicate
call(DDef, Pred, ExCtx, TPred) ->
call(TPred)
; % in the worst case we need to compile the meta-call
'$lgt_comp_ctx'(Ctx, _, ExCtx, Entity, Sender, This, Self, Prefix, [], _, ExCtx, runtime, Stack, _, _),
catch('$lgt_compile_body'(Pred, _, TPred, DPred, Ctx), Error, throw(error(Error, logtalk(call(Pred), ExCtx)))),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
catch(DPred, error(Error,_), throw(error(Error, logtalk(call(Pred), ExCtx))))
; catch(TPred, error(Error,_), throw(error(Error, logtalk(call(Pred), ExCtx))))
)
)
; '$lgt_current_category_'(Entity, Prefix, _, Def, _, Flags),
( % in the most common case we're meta-calling a user defined predicate
call(Def, Pred, ExCtx, TPred) ->
call(TPred)
; % in the worst case we need to compile the meta-call
'$lgt_comp_ctx'(Ctx, _, ExCtx, Entity, Sender, This, Self, Prefix, [], _, ExCtx, runtime, [], _, _),
catch('$lgt_compile_body'(Pred, _, TPred, DPred, Ctx), Error, throw(error(Error, logtalk(call(Pred), ExCtx)))),
( Flags /\ 512 =:= 512 ->
% category compiled in debug mode
catch(DPred, error(Error,_), throw(error(Error, logtalk(call(Pred), ExCtx))))
; catch(TPred, error(Error,_), throw(error(Error, logtalk(call(Pred), ExCtx))))
)
)
).
% '$lgt_metacall_sender'(+callable, +execution_context, +execution_context, +list)
%
% performs a meta-call in "sender" at runtime
%
% we must pass any extra arguments (a non-empty list when processing closures)
% as compilation context meta-variables to properly compile calls to control
% constructs (e.g. conjunctions) where those extra arguments must be called in
% the correct context
'$lgt_metacall_sender'(Pred, ExCtx, CallerExCtx, ExtraArgs) :-
'$lgt_execution_context'(CallerExCtx, CallerEntity, Sender, This, Self, _, Stack),
( CallerEntity == user ->
catch(Pred, error(Error,_), throw(error(Error, logtalk(call(Pred), CallerExCtx))))
; '$lgt_current_object_'(CallerEntity, CallerPrefix, _, Def, _, _, _, _, DDef, _, Flags) ->
( % in the most common case we're meta-calling a user defined static predicate
call(Def, Pred, CallerExCtx, TPred) ->
call(TPred)
; % or a user defined dynamic predicate
call(DDef, Pred, CallerExCtx, TPred) ->
call(TPred)
; % in the worst case we have a control construct or a built-in predicate
( ExtraArgs == [] ->
MetaCallCtx = []
; MetaCallCtx = ExCtx
),
'$lgt_execution_context'(NewCallerExCtx, CallerEntity, Sender, This, Self, MetaCallCtx, Stack),
'$lgt_comp_ctx'(Ctx, _, NewCallerExCtx, CallerEntity, Sender, This, Self, CallerPrefix, ExtraArgs, MetaCallCtx, NewCallerExCtx, runtime, Stack, _, _),
catch('$lgt_compile_body'(Pred, _, TPred, DPred, Ctx), Error, throw(error(Error, logtalk(call(Pred), CallerExCtx)))),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
catch(DPred, error(Error,_), throw(error(Error, logtalk(call(Pred), CallerExCtx))))
; catch(TPred, error(Error,_), throw(error(Error, logtalk(call(Pred), CallerExCtx))))
)
)
; '$lgt_current_category_'(CallerEntity, CallerPrefix, _, Def, _, Flags),
( % in the most common case we're meta-calling a user defined static predicate
call(Def, Pred, CallerExCtx, TPred) ->
call(TPred)
; % in the worst case we have a control construct or a built-in predicate
( ExtraArgs == [] ->
MetaCallCtx = []
; MetaCallCtx = ExCtx
),
'$lgt_execution_context'(NewCallerExCtx, CallerEntity, Sender, This, Self, MetaCallCtx, Stack),
'$lgt_comp_ctx'(Ctx, _, NewCallerExCtx, CallerEntity, Sender, This, Self, CallerPrefix, ExtraArgs, MetaCallCtx, NewCallerExCtx, runtime, Stack, _, _),
catch('$lgt_compile_body'(Pred, _, TPred, DPred, Ctx), Error, throw(error(Error, logtalk(call(Pred), CallerExCtx)))),
( Flags /\ 512 =:= 512 ->
% object compiled in debug mode
catch(DPred, error(Error,_), throw(error(Error, logtalk(call(Pred), CallerExCtx))))
; catch(TPred, error(Error,_), throw(error(Error, logtalk(call(Pred), CallerExCtx))))
)
)
).
% '$lgt_call_within_context'(?term, ?term, +object_identifier)
%
% calls a goal within the context of the specified object when the object and/or the
% goal are only known at runtime
%
% used mostly for debugging and for writing unit tests, the permission to perform a
% context-switching call can be disabled in a per-object basis by using the compiler
% flag "context_switching_calls"
'$lgt_call_within_context'(Obj, Goal, ExCtx) :-
'$lgt_check'(object_identifier, Obj, logtalk(Obj<
catch(Goal, Error, '$lgt_runtime_error_handler'(error(Error, logtalk(user<
( Flags /\ 256 =:= 256 ->
% object compiled with context-switching calls allowed
'$lgt_execution_context'(ObjExCtx, Obj, Obj, Obj, Obj, [], []),
( % in the most common case we're calling a user defined static predicate
call(Def, Goal, ObjExCtx, TGoal) ->
catch(TGoal, Error, '$lgt_runtime_error_handler'(error(Error, logtalk(Obj<
catch(TGoal, Error, '$lgt_runtime_error_handler'(error(Error, logtalk(Obj<
% object compiled in debug mode
catch(DGoal, Error, '$lgt_runtime_error_handler'(error(Error, logtalk(Obj<
call(TPred)
; % or the clauses for the predicate may be defined only at runtime
call(DDef, Pred, ExCtx, TPred) ->
call(TPred)
; % no definition found; fail as per closed-world assumption
fail
).
% '$lgt_call_in_this'(+callable, +execution_context)
%
% calls a dynamic predicate in "this" from within a category at runtime;
% also used to call overridden predicate definitions from complementing categories
'$lgt_call_in_this'(Pred, ExCtx) :-
'$lgt_execution_context_this_entity'(ExCtx, This, _),
'$lgt_current_object_'(This, _, Dcl, Def, _, _, _, _, DDef, _, _),
( \+ call(Dcl, Pred, _, _, _, _, _) ->
% unknown predicate
functor(Pred, Functor, Arity),
throw(error(existence_error(predicate_declaration, Functor/Arity), logtalk(Pred, ExCtx)))
; % the object definition may include some initial clauses for the predicate
call(Def, Pred, ExCtx, TPred) ->
call(TPred)
; % or the clauses for the predicate may be defined only at runtime
call(DDef, Pred, ExCtx, TPred) ->
call(TPred)
; % no definition found; fail as per closed-world assumption
fail
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% support for categories that complement objects (hot patching)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% lookup predicate declarations in any category that complements the given object
'$lgt_complemented_object'(This, ThisDcl, Alias, Scope, Meta, Flags, SCtn, TCtn) :-
'$lgt_complemented_object_'(This, _, Dcl, _, Rnm),
( call(Dcl, Alias, Scope, Meta, Flags, TCtn),
SCtn = This
; % categories can define aliases for complemented object predicates
call(Rnm, This, Pred, Alias),
Pred \= Alias,
call(ThisDcl, Pred, Scope, Meta, Flags, SCtn, TCtn)
).
% lookup predicate definitions in any category that complements the given object
'$lgt_complemented_object'(This, ThisDef, Alias, OExCtx, Call, Ctn) :-
'$lgt_complemented_object_'(This, Ctg, _, Def, Rnm),
'$lgt_execution_context_update_this_entity'(OExCtx, This, This, CExCtx, This, Ctg),
( call(Def, Alias, CExCtx, Call, Ctn)
; % categories may also define aliases for complemented object predicates
call(Rnm, This, Pred, Alias),
Pred \= Alias,
call(ThisDef, Pred, OExCtx, Call, _, Ctn)
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% debugging base support
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_debug'(+compound, @execution_context)
%
% calls all defined trace event handlers and either use a loaded debug
% handler provider for the debug event or simply call the debugging goals
% to prevent execution of code compiled in debug mode to simply fail
%
% we can have multiple trace event handlers but only one debug handler
% (the compiler prints a warning when attempting to load a second handler)
'$lgt_debug'(Event, ExCtx) :-
'$logtalk#0.trace_event#2'(Event, ExCtx, _),
fail.
'$lgt_debug'(Event, ExCtx) :-
'$logtalk#0.active_debug_handler_#1'(Provider, _),
!,
'$logtalk#0.debug_handler#3'(Provider, Event, ExCtx, _).
% top_goal(Goal, TGoal)
'$lgt_debug'(top_goal(_, TGoal), _) :-
call(TGoal).
% goal(Goal, TGoal)
'$lgt_debug'(goal(_, TGoal), _) :-
call(TGoal).
% fact(Entity, Fact, ClauseNumber, File, BeginLine)
'$lgt_debug'(fact(_, _, _, _, _), _).
% rule(Entity, Head, ClauseNumber, File, BeginLine)
'$lgt_debug'(rule(_, _, _, _, _), _).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% message printing support
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_print_message'(+atom_or_compound, +atom, +nonvar)
%
% internal predicate used by the compiler and runtime to print a message;
% we fake the execution context argument to call the corresponding method
% in the "logtalk" built-in object
'$lgt_print_message'(Kind, Message) :-
( '$lgt_built_in_entities_loaded_' ->
% "logtalk" built-in object loaded
'$lgt_execution_context'(ExCtx, logtalk, logtalk, logtalk, logtalk, [], []),
'$logtalk#0.print_message#3'(Kind, core, Message, ExCtx)
; % still compiling the default built-in entities
'$lgt_compiler_flag'(report, off) ->
% no message printing required
true
; % bare-bones message printing
write('core '), write(Kind), write(': '), writeq(Message), nl
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% compiler
%
% compiles Logtalk source files into intermediate Prolog source files
% and calls the backend Prolog compiler on the generated files
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_load_files'(@source_file_name, @list(compiler_flag))
% '$lgt_load_files'(@list(source_file_name), @list(compiler_flag))
%
% compiles to disk and then loads to memory a source file or a list of source files
%
% a call to this predicate can trigger other calls to it, therefore we *must* clean
% the compilation auxiliary predicates *before* compiling a file
'$lgt_load_files'([], _) :-
!.
'$lgt_load_files'([File| Files], Flags) :-
!,
'$lgt_clean_pp_file_clauses',
'$lgt_set_compiler_flags'(Flags),
'$lgt_load_file'(File, Flags),
'$lgt_load_files'(Files, Flags).
'$lgt_load_files'(File, Flags) :-
'$lgt_load_files'([File], Flags).
% '$lgt_load_file'(@source_file_name, @list)
%
% compiles to disk and then loads to memory a source file
'$lgt_load_file'(File, [RelativeTo| Flags]) :-
( '$lgt_source_file_name'(File, [RelativeTo| Flags], Directory, Name, Extension, SourceFile),
\+ '$lgt_file_loading_stack_'(SourceFile, Directory),
atom_concat(Name, Extension, Basename),
( '$lgt_loaded_file_'(Basename, Directory, _, _, _, _, _)
% file already loaded; possibly an embedded application in which case we
% don't want to throw a file existence error as the original source file
% may not exist, or no longer exist, on the system where we are running
; '$lgt_file_exists'(SourceFile)
) ->
true
; '$lgt_source_file_name'(File, [RelativeTo| Flags], Directory, Name, Extension, SourceFile),
'$lgt_file_loading_stack_'(SourceFile, Directory) ->
% file trying to recursively load itself
throw(error(permission_error(load, file, File), _))
; throw(error(existence_error(file, File), _))
),
( '$lgt_loaded_file_'(Basename, Directory, PreviousMode, PreviousFlags, _, _, LoadingTimeStamp),
\+ '$lgt_failed_file_'(SourceFile) ->
% we're attempting to reload a file
( '$lgt_member'(reload(Reload), PreviousFlags) ->
true
; '$lgt_compiler_flag'(reload, Reload)
),
( Reload == skip ->
% skip reloading already loaded files
'$lgt_print_message'(comment(loading), skipping_reloading_file(SourceFile, Flags)),
% but save the file loading dependency on a parent file if it exists
'$lgt_save_file_loading_dependency'(SourceFile)
; Reload == changed,
PreviousFlags == Flags,
\+ '$lgt_changed_compilation_mode'(PreviousMode, PreviousFlags),
'$lgt_file_modification_time'(SourceFile, CurrentTimeStamp),
CurrentTimeStamp @=< LoadingTimeStamp ->
% file was not modified since loaded and same explicit flags and compilation mode as before
'$lgt_print_message'(comment(loading), skipping_reloading_file(SourceFile, Flags)),
% but save the file loading dependency on a parent file if it exists
'$lgt_save_file_loading_dependency'(SourceFile)
; % we're reloading a source file
'$lgt_print_message'(silent(loading), reloading_file(SourceFile, Flags)),
'$lgt_compile_and_load_file'(Directory, Name, Extension, Basename, SourceFile, Flags, reloading),
'$lgt_print_message'(comment(loading), reloaded_file(SourceFile, Flags))
)
; % first time loading this source file or previous attempt failed due to compilation error
'$lgt_print_message'(silent(loading), loading_file(SourceFile, Flags)),
'$lgt_compile_and_load_file'(Directory, Name, Extension, Basename, SourceFile, Flags, loading),
'$lgt_print_message'(comment(loading), loaded_file(SourceFile, Flags))
).
'$lgt_compile_and_load_file'(Directory, Name, Extension, Basename, SourceFile, Flags, Action) :-
'$lgt_object_file_names'(Directory, Name, Extension, ObjectFilePid, ObjectFileDialect),
retractall('$lgt_pp_file_paths_flags_'(_, _, _, _, _)),
( '$lgt_compiler_flag'(clean, on) ->
ObjectFile = ObjectFilePid
; ObjectFile = ObjectFileDialect
),
assertz('$lgt_pp_file_paths_flags_'(Basename, Directory, SourceFile, ObjectFile, Flags)),
retractall('$lgt_failed_file_'(SourceFile)),
% save the file loading dependency on a parent file if it exists
'$lgt_save_file_loading_dependency'(SourceFile),
retractall('$lgt_file_loading_stack_'(SourceFile, Directory)),
asserta('$lgt_file_loading_stack_'(SourceFile, Directory)),
% compile the source file to an intermediate Prolog file on disk;
% a syntax error while reading the terms in a source file results
% in a printed message and failure instead of an exception but we
% need to pass the failure up to the caller
( '$lgt_compile_file'(SourceFile, Flags, ObjectFile, Action) ->
true
; retractall('$lgt_file_loading_stack_'(SourceFile, Directory)),
'$lgt_propagate_failure_to_parent_files'(SourceFile),
fail
),
% compile and load the intermediate Prolog file
'$lgt_load_compiled_file'(SourceFile, ObjectFile),
retractall('$lgt_file_loading_stack_'(SourceFile, _)),
retractall('$lgt_pp_file_paths_flags_'(_, _, _, _, _)),
% cleanup intermediate files if necessary
( '$lgt_compiler_flag'(clean, on) ->
'$lgt_delete_intermediate_files'(ObjectFilePid),
'$lgt_delete_intermediate_files'(ObjectFileDialect)
; true
).
'$lgt_save_file_loading_dependency'(SourceFile) :-
( '$lgt_file_loading_stack_'(ParentSourceFile, _),
SourceFile \== ParentSourceFile ->
% as a file can have multiple parents, we only
% ensure that there aren't duplicated entries
retractall('$lgt_parent_file_'(SourceFile, ParentSourceFile)),
asserta('$lgt_parent_file_'(SourceFile, ParentSourceFile))
; % no parent file
true
).
'$lgt_load_compiled_file'(SourceFile, ObjectFile) :-
% retrieve the backend Prolog specific file loading options
'$lgt_compiler_flag'(prolog_loader, DefaultOptions),
% loading a file can result in the redefinition of existing
% entities thus potentially invalidating cache entries
'$lgt_clean_lookup_caches',
'$lgt_report_redefined_entities',
( '$lgt_pp_file_encoding_'(SourceFile, _, Encoding, _) ->
% use the same encoding as the original source file but do not use the inferred
% bom/1 option as it would only work with some backend Prolog compilers
Options = [encoding(Encoding)| DefaultOptions]
; Options = DefaultOptions
),
% clean all runtime clauses as an initialization goal in the intermediate Prolog file
% that is loaded next may create dynamic entities
'$lgt_clean_pp_runtime_clauses',
% load the generated intermediate Prolog file but cope with unexpected error or failure
( ( catch('$lgt_load_prolog_code'(ObjectFile, SourceFile, Options), Error, true) ->
( var(Error) ->
true
; % an error while loading the generated intermediate Prolog files is usually
% caused by backend write_canonical/2 and/or read_term/3 predicate bugs
'$lgt_print_message'(error, loading_error(SourceFile, Error)),
fail
)
; '$lgt_print_message'(error, loading_failure(SourceFile)),
fail
) ->
true
; % loading of the intermediate Prolog file failed
retractall('$lgt_file_loading_stack_'(SourceFile, _)),
retractall('$lgt_pp_file_paths_flags_'(_, _, _, _, _)),
'$lgt_propagate_failure_to_parent_files'(SourceFile),
'$lgt_delete_intermediate_files'(ObjectFile),
fail
).
'$lgt_delete_intermediate_files'(ObjectFile) :-
% try to delete the intermediate Prolog file (ignore failure or error)
'$lgt_file_exists'(ObjectFile),
catch('$lgt_delete_file'(ObjectFile), _, true),
fail.
'$lgt_delete_intermediate_files'(ObjectFile) :-
% try to delete any Prolog dialect specific auxiliary files (ignore failure or error)
'$lgt_file_extension'(object, ObjectExtension),
atom_concat(Name, ObjectExtension, ObjectFile),
'$lgt_file_extension'(tmp, TmpExtension),
atom_concat(Name, TmpExtension, TmpFile),
'$lgt_file_exists'(TmpFile),
catch('$lgt_delete_file'(TmpFile), _, true),
fail.
'$lgt_delete_intermediate_files'(_).
% '$lgt_report_redefined_entities'
%
% prints a warning for all entities that are about to be redefined
%
% also retracts old runtime clauses for the entity being redefined for safety
'$lgt_report_redefined_entities' :-
( '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Entity, _, _, _, _))
; '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Entity, _, _, _, _, _))
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, _))
),
'$lgt_redefined_entity'(Entity, Type, OldFile, NewFile, Lines),
'$lgt_report_redefined_entity'(Type, Entity, OldFile, NewFile, Lines),
'$lgt_retract_old_runtime_clauses'(Type, Entity),
fail.
'$lgt_report_redefined_entities'.
% '$lgt_redefined_entity'(@entity_identifier, -atom, -atom, -atom, -pair(integer))
%
% true if an entity of the same name is already loaded; returns entity type
'$lgt_redefined_entity'(Entity, Type, OldFile, NewFile, Lines) :-
% check that an entity with the same identifier is already loaded
( '$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, Flags) ->
Type = object
; '$lgt_current_protocol_'(Entity, _, _, _, Flags) ->
Type = protocol
; '$lgt_current_category_'(Entity, _, _, _, _, Flags),
Type = category
),
( Flags /\ 1 =:= 1 ->
% built-in entity; no redefinition allowed
throw(permission_error(modify, Type, Entity))
; % redefinable entity but, in the presence of entity dynamic predicates, when
% using some backend Prolog compilers, some old dynamic clauses may persist
true
),
( % check file information using the file_lines/4 entity property, if available
'$lgt_entity_property_'(Entity, file_lines(OldBasename, OldDirectory, _, _)),
'$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, file_lines(NewBasename, NewDirectory, Start, End))) ->
atom_concat(OldDirectory, OldBasename, OldFile),
atom_concat(NewDirectory, NewBasename, NewFile),
Lines = Start-End
; % no file_lines/4 entity property (due to compilation with the source_data flag turned off)
OldFile = nil,
NewFile = nil,
Lines = '-'(-1, -1)
).
% '$lgt_report_redefined_entity'(+atom, @entity_identifier, +atom, +atom, +pair(integer))
%
% prints an informative message or a warning for a redefined entity
'$lgt_report_redefined_entity'(Type, Entity, OldFile, NewFile, Lines) :-
( OldFile == NewFile ->
% either reloading the same source file or no source file data is available; assume entity redefinition normal
'$lgt_print_message'(comment(loading), redefining_entity(Type, Entity))
; % we've conflicting entity definitions coming from different source files
'$lgt_increment_loading_warnings_counter',
'$lgt_print_message'(warning(loading), redefining_entity_from_file(NewFile, Lines, Type, Entity, OldFile))
).
% '$lgt_retract_old_runtime_clauses'(+atom, @entity_identifier)
%
% cleans all references to an entity that is about to be redefined
% from the runtime tables
'$lgt_retract_old_runtime_clauses'(object, Entity) :-
retractall('$lgt_before_event_'(_, _, _, Entity, _)),
retractall('$lgt_after_event_'(_, _, _, Entity, _)),
retractall('$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, _)),
retractall('$lgt_entity_property_'(Entity, _)),
retractall('$lgt_predicate_property_'(Entity, _, _)),
retractall('$lgt_implements_protocol_'(Entity, _, _)),
retractall('$lgt_imports_category_'(Entity, _, _)),
retractall('$lgt_instantiates_class_'(Entity, _, _)),
retractall('$lgt_specializes_class_'(Entity, _, _)),
retractall('$lgt_extends_object_'(Entity, _, _)),
retractall('$lgt_current_engine_'(Entity, _, _, _)).
'$lgt_retract_old_runtime_clauses'(protocol, Entity) :-
retractall('$lgt_current_protocol_'(Entity, _, _, _, _)),
retractall('$lgt_entity_property_'(Entity, _)),
retractall('$lgt_predicate_property_'(Entity, _, _)),
retractall('$lgt_extends_protocol_'(Entity, _, _)).
'$lgt_retract_old_runtime_clauses'(category, Entity) :-
retractall('$lgt_current_category_'(Entity, _, _, _, _, _)),
retractall('$lgt_entity_property_'(Entity, _)),
retractall('$lgt_predicate_property_'(Entity, _, _)),
retractall('$lgt_implements_protocol_'(Entity, _, _)),
retractall('$lgt_extends_category_'(Entity, _, _)),
retractall('$lgt_complemented_object_'(_, Entity, _, _, _)).
% '$lgt_compile_files'(@source_file_name, @list(compiler_flag))
% '$lgt_compile_files'(@list(source_file_name), @list(compiler_flag))
%
% compiles to disk a source file or a list of source files
%
% a call to this predicate can trigger other calls to it, therefore we *must*
% clean the compilation auxiliary predicates *before* compiling a file
'$lgt_compile_files'([], _) :-
!,
retractall('$lgt_pp_file_paths_flags_'(_, _, _, _, _)).
'$lgt_compile_files'([File| Files], [RelativeTo| Flags]) :-
!,
'$lgt_clean_pp_file_clauses',
'$lgt_set_compiler_flags'(Flags),
( '$lgt_source_file_name'(File, [RelativeTo| Flags], Directory, Name, Extension, SourceFile),
'$lgt_file_exists'(SourceFile) ->
true
; throw(error(existence_error(file, File), _))
),
'$lgt_object_file_names'(Directory, Name, Extension, ObjectFilePid, ObjectFileDialect),
atom_concat(Name, Extension, Basename),
retractall('$lgt_pp_file_paths_flags_'(_, _, _, _, _)),
( '$lgt_compiler_flag'(clean, on) ->
ObjectFile = ObjectFilePid
; ObjectFile = ObjectFileDialect
),
assertz('$lgt_pp_file_paths_flags_'(Basename, Directory, SourceFile, ObjectFile, Flags)),
'$lgt_compile_file'(SourceFile, Flags, ObjectFile, compiling),
'$lgt_compile_files'(Files, [RelativeTo| Flags]).
'$lgt_compile_files'(File, Flags) :-
'$lgt_compile_files'([File], Flags).
% '$lgt_compile_file'(@source_file_name, @list, @source_file_name, +atom)
%
% compiles to disk a source file
'$lgt_compile_file'(SourceFile, Flags, ObjectFile, Action) :-
( % ensure that we disregard any existing the intermediate Prolog file
% if we're reloading as that may be required due to different flags
Action \== reloading,
% interpret a clean(on) setting as (also) meaning that any
% existing intermediate Prolog files should be disregarded
'$lgt_compiler_flag'(clean, off),
'$lgt_file_exists'(ObjectFile),
'$lgt_up_to_date_object_file'(SourceFile, ObjectFile) ->
'$lgt_print_message'(silent(compiling), up_to_date_file(SourceFile, Flags))
; % the intermediate Prolog file doesn't exist or it's outdated
'$lgt_print_message'(silent(compiling), compiling_file(SourceFile, Flags)),
'$lgt_compile_file'(SourceFile, ObjectFile),
'$lgt_compiler_flag'(prolog_compiler, Options),
'$lgt_compile_prolog_code'(ObjectFile, SourceFile, Options),
( Action == loading ->
'$lgt_print_message'(silent(compiling), compiled_file(SourceFile, Flags))
; % Action == compiling,
'$lgt_print_message'(comment(compiling), compiled_file(SourceFile, Flags))
)
).
% a file can be loaded by a loader file that, in turn, may also be loaded by
% another loader file; propagating a file loading failure to its parent files
% provides better top-level usability allowing reloading of fixed files by
% simply reloading the loader files, which also ensures loading of any files
% to be loaded after the broken file that were not loaded in the previous
% attempt
'$lgt_propagate_failure_to_parent_files'(File) :-
( '$lgt_parent_file_'(File, Parent) ->
'$lgt_propagate_failure_to_parent_files'(Parent)
; assertz('$lgt_failed_file_'(File))
).
% '$lgt_up_to_date_object_file'(+atom, +atom)
%
% Check that the object file is up-to-date
'$lgt_up_to_date_object_file'(SourceFile, ObjectFile) :-
'$lgt_file_modification_time'(SourceFile, SourceFileTime),
'$lgt_file_modification_time'(ObjectFile, ObjectFileTime),
SourceFileTime @=< ObjectFileTime.
% '$lgt_write_entity_code'(+atom, @entity_identifier)
%
% writes to disk the entity compiled code
'$lgt_write_entity_code'(object, Obj) :-
'$lgt_pp_object_'(Obj, _, _, _, _, _, _, _, _, Rnm, _),
'$lgt_write_entity_code'(Rnm).
'$lgt_write_entity_code'(protocol, Ptc) :-
'$lgt_pp_protocol_'(Ptc, _, _, Rnm, _),
'$lgt_write_entity_code'(Rnm).
'$lgt_write_entity_code'(category, Ctg) :-
'$lgt_pp_category_'(Ctg, _, _, _, Rnm, _),
'$lgt_write_entity_code'(Rnm).
'$lgt_write_entity_code'(Rnm) :-
'$lgt_pp_file_paths_flags_'(_, _, Path, _, _),
% avoid a spurious choice-point with some backend Prolog compilers
stream_property(Output, alias(logtalk_compiler_output)), !,
catch(
'$lgt_write_entity_code'(Output, Path, Rnm),
Error,
'$lgt_compiler_output_stream_error_handler'(Output, Error)
).
'$lgt_write_entity_code'(Output, Path, Rnm) :-
% write any plain Prolog terms that may precede the entity definition
'$lgt_write_prolog_terms'(Output, Path),
'$lgt_write_entity_directives'(Output, Path),
'$lgt_write_entity_clauses'(Output, Path, Rnm).
% '$lgt_source_file_name'(+atom, +list(callable), -atom, -atom, -atom, -atom)
%
% converts a source file specification into a source file directory, basename,
% and full path
%
% the source file specification can be either absolute or relative and may or
% may not include a file name extension
%
% when the source file specification doesn't include a file extension, this
% predicate provides a solution for each defined Logtalk and Prolog source
% file extension; callers should test if the returned full path exists and
% commit to that solution when not simply generating all possible solutions
'$lgt_source_file_name'(FilePath, Flags, Directory, Name, Extension, SourceFile) :-
( ( sub_atom(FilePath, 0, 1, _, '/')
% this covers the case of embedded applications created in a POSIX system
% and being run on a Windows system where a path starting with a slash
% would not be recognized as an absolute path by '$lgt_expand_path'/2
; '$lgt_expand_path'(FilePath, FilePath)
) ->
% assume full path
SourceFile0 = FilePath
; % assume relative path and try possible alternatives
( once('$lgt_file_loading_stack_'(_, ParentDirectory)),
% parent file exists; try first a path relative to its directory
atom_concat(ParentDirectory, FilePath, SourceFile0)
; ( '$lgt_member'(relative_to(BasePath), Flags)
; '$lgt_member'('$relative_to'(BasePath), Flags)
),
( sub_atom(BasePath, _, 1, 0, '/') ->
atom_concat(BasePath, FilePath, SourceFile0)
; atom_concat(BasePath, '/', BasePathSlash),
atom_concat(BasePathSlash, FilePath, SourceFile0)
)
; % we may have a relative file path without any parent file
% (e.g. when the user changes the working directory to the
% directory containing the file to be loaded)
'$lgt_expand_path'(FilePath, SourceFile0)
)
),
'$lgt_decompose_file_name'(SourceFile0, Directory, Name0, Extension0),
( % file extensions are defined in the Prolog adapter files (there
% might be multiple extensions defined for the same type of file)
'$lgt_file_extension'(logtalk, Extension0) ->
% declared extension for this type of file is present
SourceFile = SourceFile0,
Name = Name0,
Extension = Extension0
; '$lgt_file_extension'(prolog, Extension0) ->
% assume Prolog file being compiled as a Logtalk file
SourceFile = SourceFile0,
Name = Name0,
Extension = Extension0
; % no Logtalk or Prolog extension for this type of file; generate possible
% basenames starting with Logtalk extensions followed by Prolog extensions
( '$lgt_file_extension'(logtalk, Extension)
; '$lgt_file_extension'(prolog, Extension)
),
atom_concat(SourceFile0, Extension, SourceFile),
atom_concat(Name0, Extension0, Name)
; % use basename as-is
SourceFile = SourceFile0,
atom_concat(Name0, Extension0, Name),
Extension = ''
).
% '$lgt_object_file_names'(+atom, +atom, +atom, -atom)
%
% converts a source file full path into two object file full paths: one that
% includes the process identifier for use when the clean flag is turned on
% (to allow parallel Logtalk processes) and one that includes the backend
% identifier for use when the clean flag is turned off (to avoid file name
% conflicts when running with backends generate the same directory hashes)
'$lgt_object_file_names'(SourceDirectory, SourceName, SourceExtension, ObjectFilePid, ObjectFileDialect) :-
% temporary files are stored in the defined scratch directory
'$lgt_compiler_flag'(scratch_directory, ScratchDirectory0),
% allow using library notation to specify the scratch directory
'$lgt_check_and_expand_source_file'(ScratchDirectory0, ScratchDirectory1),
% make sure that the scratch directory path ends with a slash
( sub_atom(ScratchDirectory1, _, _, 0, '/') ->
ScratchDirectory = ScratchDirectory1
; atom_concat(ScratchDirectory1, '/', ScratchDirectory)
),
( sub_atom(ScratchDirectory, 0, 2, _, './') ->
% relative directory path
sub_atom(ScratchDirectory, 2, _, 0, ScratchDirectorySuffix),
atom_concat(SourceDirectory, ScratchDirectorySuffix, ObjectDirectory)
; % assume absolute directory path
ObjectDirectory = ScratchDirectory
),
% add a suffix based on the original extension to the file name to avoid
% intermediate and temporary file name conflicts when compiling two or
% more source files that share the same name but use different extensions
( '$lgt_source_extension_suffix'(SourceExtension, Suffix) ->
true
; sub_atom(SourceExtension, 1, _, 0, Suffix0) ->
atom_concat('_', Suffix0, Suffix)
),
% append (if supported by the backend compiler) a directory hash value to the
% intermediate Prolog file name to try to avoid file name collisions when
% collecting all the intermediate files in the same directory (possibly for
% embedding); when compiling with the "clean" flag turned on (its default
% value), also include in the file name the process identifier to avoid file
% name clashes when running parallel Logtalk processes
'$lgt_directory_hashes'(SourceDirectory, HashDialect, HashPid),
'$lgt_object_file_name'(ObjectDirectory, SourceName, HashDialect, Suffix, ObjectFileDialect),
'$lgt_object_file_name'(ObjectDirectory, SourceName, HashPid, Suffix, ObjectFilePid).
'$lgt_object_file_name'(ObjectDirectory, SourceName, Hash, Suffix, ObjectFile) :-
atom_concat(SourceName, Hash, ObjectName0),
atom_concat(ObjectName0, Suffix, ObjectName),
% there must be a single object file extension defined in the Prolog adapter files
'$lgt_file_extension'(object, ObjectExtension),
atom_concat(ObjectName, ObjectExtension, ObjectBasename),
atom_concat(ObjectDirectory, ObjectBasename, ObjectFile),
% make sure the scratch directory exists
'$lgt_make_directory'(ObjectDirectory).
% common source extensions and corresponding precomputed suffixes
'$lgt_source_extension_suffix'('.lgt', '_lgt').
'$lgt_source_extension_suffix'('.logtalk', '_logtalk').
'$lgt_source_extension_suffix'('.pl', '_pl').
'$lgt_source_extension_suffix'('.pro', '_pro').
'$lgt_source_extension_suffix'('.prolog', '_prolog').
'$lgt_source_extension_suffix'('', '').
% '$lgt_compile_file'(+atom, +atom)
%
% compiles a source file storing the resulting code in memory
'$lgt_compile_file'(SourceFile, ObjectFile) :-
% open the Logtalk source code file for reading
catch(
'$lgt_open'(SourceFile, read, Input, [alias(logtalk_compiler_input)]),
OpenError,
'$lgt_compiler_stream_error_handler'(OpenError)
),
% look for an encoding/1 directive that, when present, must be the first term on a source file
catch(
'$lgt_read_file_term'(SourceFile, Input, Term, Singletons, Lines),
InputError,
'$lgt_compiler_first_term_error_handler'(SourceFile, Lines, InputError)
),
catch(
'$lgt_check_for_encoding_directive'(Term, SourceFile, Lines, Input, NewInput, [alias(logtalk_compiler_input)], OutputOptions),
FirstTermError,
'$lgt_compiler_first_term_error_handler'(SourceFile, Lines, FirstTermError)
),
% open a Prolog file for writing the generated code using any found encoding/1 directive
catch(
'$lgt_open'(ObjectFile, write, Output, [alias(logtalk_compiler_output)| OutputOptions]),
OpenError,
'$lgt_compiler_stream_error_handler'(OpenError)
),
catch(
'$lgt_write_encoding_directive'(Output, SourceFile),
WriteError,
'$lgt_compiler_stream_error_handler'(WriteError)
),
% generate a begin_of_file term for use by the term-expansion mechanism
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, compile(user,_,_), _, 0-0, _),
catch(
'$lgt_compile_file_term'(begin_of_file, Ctx),
Error,
'$lgt_compiler_error_handler'(Error)
),
% read and compile the remaining terms in the Logtalk source file
catch(
'$lgt_compile_file_term'(Term, Singletons, Lines, SourceFile, NewInput),
Error,
'$lgt_compiler_error_handler'(Error)
),
'$lgt_close'(NewInput),
% finish writing the generated Prolog file
catch(
'$lgt_write_runtime_tables'(Output),
OutputError,
'$lgt_compiler_output_stream_error_handler'(Output, OutputError)
),
'$lgt_close'(Output),
'$lgt_restore_global_operator_table',
'$lgt_check_file_naming'.
'$lgt_write_runtime_tables'(Output) :-
'$lgt_generate_loaded_file_table_entry'(SourceFile),
% write out any Prolog code occurring after the last source file entity
'$lgt_write_prolog_terms'(Output, SourceFile),
% write entity runtime directives and clauses
'$lgt_write_runtime_clauses'(Output, SourceFile),
% write initialization/1 directive at the end of the file to improve
% compatibility with non-ISO compliant Prolog compilers
'$lgt_write_initialization_directive'(Output, SourceFile).
'$lgt_generate_loaded_file_table_entry'(SourceFile) :-
'$lgt_pp_file_paths_flags_'(Basename, Directory, SourceFile, ObjectFile, Flags),
% the make predicate will reload a file if the compilation mode changed ...
( '$lgt_compiler_flag'(debug, on) ->
Mode = debug
; '$lgt_compiler_flag'(optimize, on) ->
Mode = optimal
; Mode = normal
),
% ... or if the file modification date changed (e.g. to fix compilation errors)
'$lgt_file_modification_time'(SourceFile, TimeStamp),
% compute text properties that are only available after successful file compilation
( '$lgt_pp_file_encoding_'(SourceFile, Encoding, _, _) ->
( '$lgt_pp_file_bom_'(SourceFile, BOM) ->
TextProperties = [encoding(Encoding), BOM]
; TextProperties = [encoding(Encoding)]
)
; TextProperties = []
),
assertz('$lgt_pp_runtime_clause_'('$lgt_loaded_file_'(Basename, Directory, Mode, Flags, TextProperties, ObjectFile, TimeStamp))).
% '$lgt_check_for_encoding_directive'(?term, +atom, +pair(integer), @stream, -stream, +list, -list)
%
% encoding/1 directives must be used during entity compilation and for the
% encoding of the generated Prolog files; a BOM present in the source file
% is inherited by the generated Prolog file
'$lgt_check_for_encoding_directive'(Term, _, _, _, _, _, _) :-
var(Term),
throw(error(instantiation_error, term)).
'$lgt_check_for_encoding_directive'((:- Term), _, _, _, _, _, _) :-
var(Term),
throw(error(instantiation_error, directive(Term))).
'$lgt_check_for_encoding_directive'((:- encoding(Encoding)), SourceFile, BeginLine-EndLine, Input, NewInput, InputOptions, [encoding(PrologEncoding)|BOM]) :-
!,
( var(Encoding) ->
throw(error(instantiation_error, directive(encoding(Encoding))))
; '$lgt_prolog_feature'(encoding_directive, EncodingDirective),
% avoid a trivial failure warning with some Prolog backends
% by checking the flag value in a separate goal
EncodingDirective == unsupported ->
throw(error(resource_error(text_encoding_support), directive(encoding(Encoding))))
; % the conversion between Logtalk and Prolog encodings is defined in the adapter files
( '$lgt_decompose_file_name'(SourceFile, _, _, Extension),
'$lgt_file_extension'(prolog, Extension),
'$lgt_logtalk_prolog_encoding'(LogtalkEncoding, Encoding, Input) ->
% converted Prolog specific encoding to Logtalk encoding;
% possibly compiling a module as an object
PrologEncoding = Encoding
; LogtalkEncoding = Encoding,
'$lgt_logtalk_prolog_encoding'(LogtalkEncoding, PrologEncoding, Input)
) ->
assertz('$lgt_pp_file_encoding_'(SourceFile, LogtalkEncoding, PrologEncoding, BeginLine)),
% check that the encoding/1 directive is found in the first line
( BeginLine =:= 1 ->
true
; '$lgt_compiler_flag'(encodings, silent) ->
true
; '$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(encodings), misplaced_encoding_directive(SourceFile, BeginLine-EndLine))
),
% close and reopen the source file using the specified encoding
'$lgt_close'(Input),
'$lgt_open'(SourceFile, read, NewInput, [encoding(PrologEncoding)| InputOptions]),
( ( catch(stream_property(NewInput, bom(Boolean)), _, fail)
% SWI-Prolog and YAP
; catch(stream_property(NewInput, encoding_signature(Boolean)), _, fail)
% SICStus Prolog
) ->
BOM = [bom(Boolean)],
assertz('$lgt_pp_file_bom_'(SourceFile, bom(Boolean)))
; BOM = []
),
% throw away the already processed encoding/1 directive
'$lgt_read_file_term'(SourceFile, NewInput, _, _, _)
; % encoding not recognized
atom(Encoding) ->
throw(error(domain_error(text_encoding, Encoding), directive(encoding(Encoding))))
; throw(error(type_error(atom, Encoding), directive(encoding(Encoding))))
).
% assume no encoding/1 directive present on the source file
'$lgt_check_for_encoding_directive'(_, _, _, Input, Input, _, []).
% as per coding guidelines, the basename of a file that defines a single
% entity should by the name of the entity or, in the case of parametric
% entities, the name of the entity concatenated with the number of the
% parameters, possible separated by an underscore
'$lgt_check_file_naming' :-
( '$lgt_compiler_flag'(naming, warning),
findall(
Entity,
( '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Entity, _, _, _, _))
; '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Entity, _, _, _, _, _))
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, _))
),
[Single]
) ->
'$lgt_pp_file_paths_flags_'(Basename, _, SourceFile, _, _),
( functor(Single, Name, Arity),
( Expected = Name
; number_codes(Arity, ArityCodes),
( atom_codes(ArityAtom, [95| ArityCodes])
; atom_codes(ArityAtom, ArityCodes)
),
atom_concat(Name, ArityAtom, Expected)
),
'$lgt_file_extension'(logtalk, Extension),
atom_concat(Expected, Extension, Basename) ->
true
; '$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), file_and_entity_names_differ(SourceFile, Single))
)
; true
).
% '$lgt_compile_file_term'(@term, +list, +pair(integer), +atom, @stream)
'$lgt_compile_file_term'((-), _, _, _, _) :-
% catch variables
throw(error(instantiation_error, term)).
'$lgt_compile_file_term'(end_of_file, _, Lines, _, _) :-
!,
% set the initial compilation context and the position for compiling the end_of_file term
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, compile(user,_,_), _, Lines, _),
% allow for term-expansion of the end_of_file term
'$lgt_compile_file_term'(end_of_file, Ctx).
'$lgt_compile_file_term'(Term, _, _, File, Input) :-
'$lgt_pp_cc_skipping_',
% we're performing conditional compilation and skipping terms ...
\+ '$lgt_is_conditional_compilation_directive'(Term),
% ... except for conditional compilation directives
!,
'$lgt_read_file_term'(File, Input, Next, NextSingletons, NextLines),
'$lgt_compile_file_term'(Next, NextSingletons, NextLines, File, Input).
'$lgt_compile_file_term'(Term, Singletons, Lines, File, Input) :-
'$lgt_report_singleton_variables'(Singletons, Term, File, Lines),
% set the initial compilation context and the position for compiling the term
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, compile(user,_,_), _, Lines, _),
'$lgt_compile_file_term'(Term, Ctx),
'$lgt_read_file_term'(File, Input, Next, NextSingletons, NextLines),
'$lgt_compile_file_term'(Next, NextSingletons, NextLines, File, Input).
% '$lgt_add_referenced_object'(@object_identifier, @compilation_context)
%
% adds referenced object for later checking of references to unknown objects;
% we also save the line numbers for the first reference to the object
%
% the definition is optimized to minimize the number of inferences for
% runtime resolved ::/2 calls
'$lgt_add_referenced_object'(Obj, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, Mode),
( Mode == runtime ->
true
; Mode = compile(aux,_,_) ->
true
; % compiling a reference in a source file
'$lgt_pp_referenced_object_'(Obj, _, _) ->
% not the first reference to this object
true
; atom(Obj) ->
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_referenced_object_'(Obj, File, Lines))
; % parametric object
'$lgt_term_template'(Obj, Template),
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_referenced_object_'(Template, File, Lines))
).
% '$lgt_add_referenced_protocol'(@protocol_identifier, @compilation_context)
%
% adds referenced protocol for later checking of references to unknown protocols
% we also save the line numbers for the first reference to the protocol
'$lgt_add_referenced_protocol'(Ptc, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, Mode),
( Mode == runtime ->
true
; Mode = compile(aux,_,_) ->
true
; % compiling a reference in a source file
'$lgt_pp_referenced_protocol_'(Ptc, _, _) ->
% not the first reference to this protocol
true
; '$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_referenced_protocol_'(Ptc, File, Lines))
).
% '$lgt_add_referenced_category'(@category_identifier, @compilation_context)
%
% adds referenced category for later checking of references to unknown categories
% we also save the line numbers for the first reference to the category
'$lgt_add_referenced_category'(Ctg, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, Mode),
( Mode == runtime ->
true
; Mode = compile(aux,_,_) ->
true
; % compiling a reference in a source file
'$lgt_pp_referenced_category_'(Ctg, _, _) ->
% not the first reference to this category
true
; atom(Ctg) ->
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_referenced_category_'(Ctg, File, Lines))
; % parametric category
'$lgt_term_template'(Ctg, Template),
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_referenced_category_'(Template, File, Lines))
).
% '$lgt_add_referenced_module'(@term, @compilation_context)
%
% adds referenced module for later checking of references to unknown modules;
% we also save the line numbers for the first reference to the module
'$lgt_add_referenced_module'(Module, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, Mode),
( Mode == runtime ->
true
; Mode = compile(aux,_,_) ->
true
; % compiling a reference in a source file
var(Module) ->
% module instantiated only at runtime
true
; '$lgt_pp_referenced_module_'(Module, _, _) ->
% not the first reference to this module
true
; '$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_referenced_module_'(Module, File, Lines))
).
% '$lgt_add_referenced_object_message'(@compilation_mode, @term, @callable, @callable, @term)
%
% adds referenced object and message for supporting using reflection to
% retrieve cross-reference information
'$lgt_add_referenced_object_message'(runtime, _, _, _, _).
'$lgt_add_referenced_object_message'(compile(aux,_,_), _, _, _, _) :-
!.
'$lgt_add_referenced_object_message'(compile(user,_,_), Obj, Pred, Alias, Head) :-
( var(Head) ->
% not compiling a clause
true
; % add reference if first but be careful to not instantiate the object argument which may only be known at runtime
functor(Pred, PredFunctor, PredArity),
functor(Head, HeadFunctor, HeadArity),
'$lgt_source_file_context'(File, Lines),
( \+ \+ '$lgt_pp_referenced_object_message_'(Obj, PredFunctor/PredArity, _, HeadFunctor/HeadArity, File, Lines) ->
true
; functor(Alias, AliasFunctor, AliasArity),
( compound(Obj) ->
% compile-time parametric object
'$lgt_term_template'(Obj, Template),
assertz('$lgt_pp_referenced_object_message_'(Template, PredFunctor/PredArity, AliasFunctor/AliasArity, HeadFunctor/HeadArity, File, Lines))
; % runtime instantiated object or non-parametric object
assertz('$lgt_pp_referenced_object_message_'(Obj, PredFunctor/PredArity, AliasFunctor/AliasArity, HeadFunctor/HeadArity, File, Lines))
)
)
).
% '$lgt_add_referenced_module_predicate'(@compilation_mode, @term, @callable, @callable, @term)
%
% adds referenced module for later checking of references to unknown modules
% we also save the line numbers for the first reference to the module
'$lgt_add_referenced_module_predicate'(runtime, _, _, _, _).
'$lgt_add_referenced_module_predicate'(compile(aux,_,_), _, _, _, _) :-
!.
'$lgt_add_referenced_module_predicate'(compile(user,_,_), Module, Pred, Alias, Head) :-
( var(Head) ->
% not compiling a clause
true
; % add reference if first but be careful to not instantiate the module argument which may only be known at runtime
functor(Pred, PredFunctor, PredArity),
functor(Head, HeadFunctor, HeadArity),
'$lgt_source_file_context'(File, Lines),
( \+ \+ '$lgt_pp_referenced_module_predicate_'(Module, PredFunctor/PredArity, _, HeadFunctor/HeadArity, File, Lines) ->
true
; functor(Alias, AliasFunctor, AliasArity),
assertz('$lgt_pp_referenced_module_predicate_'(Module, PredFunctor/PredArity, AliasFunctor/AliasArity, HeadFunctor/HeadArity, File, Lines))
)
).
% '$lgt_add_entity_source_data'(@atom, @entity_identifier)
%
% adds entity source data when the corresponding flag is turned on
'$lgt_add_entity_source_data'(Kind, Entity) :-
( '$lgt_compiler_flag'(source_data, on) ->
'$lgt_pp_file_paths_flags_'(_, _, MainFile, _, _),
'$lgt_add_entity_properties'(Kind, Entity, MainFile),
'$lgt_add_entity_predicate_properties'(Entity, MainFile)
; true
).
% '$lgt_add_entity_properties'(@atom, @entity_identifier, +atom)
%
% adds entity properties related to the entity source file
'$lgt_add_entity_properties'(Kind, Entity, _) :-
( Kind == object ->
'$lgt_pp_referenced_object_'(Entity, _, StartDirective-EndDirective)
; Kind == protocol ->
'$lgt_pp_referenced_protocol_'(Entity, _, StartDirective-EndDirective)
; % Kind == category,
'$lgt_pp_referenced_category_'(Entity, _, StartDirective-EndDirective)
),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, directive(StartDirective, EndDirective)))),
'$lgt_pp_file_paths_flags_'(Basename, Directory, _, _, _),
'$lgt_pp_entity_lines_'(Entity, Start-End),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, file_lines(Basename, Directory, Start, End)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_referenced_object_message_'(Object, PredicateFunctor/PredicateArity, AliasFunctor/AliasArity, Caller, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
functor(Predicate, PredicateFunctor, PredicateArity),
( '$lgt_pp_uses_non_terminal_'(Object, _, _, Predicate, _, _, _, _) ->
PredicateArity2 is PredicateArity - 2,
NonTerminal = PredicateFunctor//PredicateArity2
; NonTerminal = no
),
( PredicateFunctor/PredicateArity == AliasFunctor/AliasArity ->
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(Object::PredicateFunctor/PredicateArity, Caller, no, NonTerminal, Location))))
; assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(Object::PredicateFunctor/PredicateArity, Caller, AliasFunctor/AliasArity, NonTerminal, Location))))
),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_referenced_module_predicate_'(Module, PredicateFunctor/PredicateArity, AliasFunctor/AliasArity, Caller, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
functor(Predicate, PredicateFunctor, PredicateArity),
( '$lgt_pp_use_module_non_terminal_'(Module, _, _, Predicate, _, _, _, _) ->
PredicateArity2 is PredicateArity - 2,
NonTerminal = PredicateFunctor//PredicateArity2
; NonTerminal = no
),
( PredicateFunctor/PredicateArity == AliasFunctor/AliasArity ->
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(':'(Module,PredicateFunctor/PredicateArity), Caller, no, NonTerminal, Location))))
; assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(':'(Module,PredicateFunctor/PredicateArity), Caller, AliasFunctor/AliasArity, NonTerminal, Location))))
),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_calls_self_predicate_'(Predicate, Caller, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(::Predicate, Caller, no, no, Location)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_calls_super_predicate_'(Predicate, Caller, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(^^Predicate, Caller, no, no, Location)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_calls_predicate_'(Predicate, _, Caller, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, calls(Predicate, Caller, no, no, Location)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_updates_predicate_'(Dynamic, Updater, File, Lines),
'$lgt_updates_property_alias_non_terminal'(Dynamic, Alias, NonTerminal),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, updates(Dynamic, Updater, Alias, NonTerminal, Location)))),
fail.
'$lgt_add_entity_properties'(_, Entity, _) :-
'$lgt_pp_entity_info_'(Info, _, _),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, info(Info)))),
fail.
'$lgt_add_entity_properties'(_, Entity, _) :-
findall(Define, '$lgt_pp_number_of_clauses_rules_'(_, _, Define, _), Defines),
'$lgt_sum_list'(Defines, TotalDefines),
findall(
AuxDefine,
( '$lgt_pp_defines_predicate_'(_, Functor/Arity, _, _, _, aux),
'$lgt_pp_number_of_clauses_rules_'(Functor, Arity, AuxDefine, _)
),
AuxDefines
),
'$lgt_sum_list'(AuxDefines, TotalAuxDefines),
findall(Provide, '$lgt_pp_number_of_clauses_rules_'(_, _, _, Provide, _), Provides),
'$lgt_sum_list'(Provides, TotalProvides),
Total is TotalDefines + TotalProvides,
TotalUser is Total - TotalAuxDefines,
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, number_of_clauses(Total, TotalUser)))),
fail.
'$lgt_add_entity_properties'(_, Entity, _) :-
findall(Define, '$lgt_pp_number_of_clauses_rules_'(_, _, _, Define), Defines),
'$lgt_sum_list'(Defines, TotalDefines),
findall(
AuxDefine,
( '$lgt_pp_defines_predicate_'(_, Functor/Arity, _, _, _, aux),
'$lgt_pp_number_of_clauses_rules_'(Functor, Arity, _, AuxDefine)
),
AuxDefines
),
'$lgt_sum_list'(AuxDefines, TotalAuxDefines),
findall(Provide, '$lgt_pp_number_of_clauses_rules_'(_, _, _, _, Provide), Provides),
'$lgt_sum_list'(Provides, TotalProvides),
Total is TotalDefines + TotalProvides,
TotalUser is Total - TotalAuxDefines,
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, number_of_rules(Total, TotalUser)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_object_alias_'(Original, Alias, _, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, object_alias(Original, Alias, Location)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_module_alias_'(Original, Alias, _, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, module_alias(Original, Alias, Location)))),
fail.
'$lgt_add_entity_properties'(_, Entity, MainFile) :-
'$lgt_pp_predicate_alias_'(For, Original, Alias, NonTerminalFlag, File, Lines),
'$lgt_property_location'(MainFile, File, Lines, Location),
functor(Original, OriginalFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, predicate_alias(For, OriginalFunctor/Arity, AliasFunctor/Arity, NonTerminalFlag, Location)))),
fail.
'$lgt_add_entity_properties'(_, _, _).
% auxiliary predicate to compute the updates/2 object/category property
% alias and non-terminal indicators for the update predicate
'$lgt_updates_property_alias_non_terminal'(Object::PredicateFunctor/PredicateArity, AliasIndicator, NonTerminalIndicator) :-
!,
functor(Predicate, PredicateFunctor, PredicateArity),
( '$lgt_pp_uses_predicate_'(Object, Predicate, Alias, _, _, _) ->
functor(Alias, AliasFunctor, AliasArity),
AliasIndicator = AliasFunctor/AliasArity
; AliasIndicator = no
),
( '$lgt_pp_uses_non_terminal_'(Object, _, _, Predicate, _, _, _, _) ->
NonTerminalArity is PredicateArity - 2,
NonTerminalIndicator = PredicateFunctor//NonTerminalArity
; NonTerminalIndicator = no
).
'$lgt_updates_property_alias_non_terminal'(':'(Module,PredicateFunctor/PredicateArity), AliasIndicator, NonTerminalIndicator) :-
!,
functor(Predicate, PredicateFunctor, PredicateArity),
( '$lgt_pp_use_module_predicate_'(Module, Predicate, Alias, _, _, _) ->
functor(Alias, AliasFunctor, AliasArity),
AliasIndicator = AliasFunctor/AliasArity
; AliasIndicator = no
),
( '$lgt_pp_use_module_non_terminal_'(Module, _, _, Predicate, _, _, _, _) ->
NonTerminalArity is PredicateArity - 2,
NonTerminalIndicator = PredicateFunctor//NonTerminalArity
; NonTerminalIndicator = no
).
'$lgt_updates_property_alias_non_terminal'(_, no, no).
% '$lgt_add_entity_predicate_properties'(@entity_identifier, +atom)
%
% saves all entity predicate properties (at the end of entity compilation)
% for use with the reflection built-in predicates and methods
'$lgt_add_entity_predicate_properties'(Entity, MainFile) :-
'$lgt_pp_predicate_definition_location_'(Other, Functor, Arity, File, Lines),
% multifile predicate clauses defined in Entity for Other
'$lgt_property_location'(MainFile, File, Lines, Location),
'$lgt_pp_number_of_clauses_rules_'(Other, Functor, Arity, Clauses, Rules),
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/Arity, clauses_rules_location_to(Clauses,Rules,Location,Other)))),
fail.
'$lgt_add_entity_predicate_properties'(Entity, MainFile) :-
'$lgt_pp_predicate_declaration_location_'(Functor, Arity, File, Lines),
% local predicate clauses
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/Arity, declaration_location(Location)))),
\+ '$lgt_pp_defines_predicate_'(_, Functor/Arity, _, _, _, _),
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/Arity, flags_clauses_rules_location(0, 0, 0, 0-0)))),
fail.
'$lgt_add_entity_predicate_properties'(Entity, MainFile) :-
'$lgt_pp_defines_predicate_'(_, Functor/Arity, _, _, _, Origin),
( '$lgt_pp_predicate_recursive_calls_'(Functor, Arity, _) ->
Flags0 is 8
; Flags0 is 0
),
( '$lgt_pp_inline_predicate_'(Functor/Arity) ->
Flags1 is Flags0 + 4
; Flags1 is Flags0
),
( '$lgt_pp_defines_non_terminal_'(Functor, _, Arity) ->
Flags2 is Flags1 + 2
; Flags2 is Flags1
),
( Origin == aux ->
Flags is Flags2 + 1,
File = MainFile,
Lines = 0-0
; Flags is Flags2,
'$lgt_pp_predicate_definition_location_'(Functor, Arity, File, Lines)
),
'$lgt_pp_number_of_clauses_rules_'(Functor, Arity, Clauses, Rules),
'$lgt_property_location'(MainFile, File, Lines, Location),
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/Arity, flags_clauses_rules_location(Flags, Clauses, Rules, Location)))),
fail.
'$lgt_add_entity_predicate_properties'(Entity, _) :-
'$lgt_pp_mode_'(Mode, Solutions, _, _),
functor(Mode, Functor, Arity),
( '$lgt_pp_non_terminal_'(Functor, Arity, ExtArity) ->
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/ExtArity, mode(Mode, Solutions))))
; assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/Arity, mode(Mode, Solutions))))
),
fail.
'$lgt_add_entity_predicate_properties'(Entity, _) :-
'$lgt_pp_predicate_info_'(Predicate, Info, _, _),
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Predicate, info(Info)))),
fail.
'$lgt_add_entity_predicate_properties'(_, _).
% the property location is the lines pair when found on the main file
% or a include(File,Lines) term when found in an included file
'$lgt_property_location'(MainFile, MainFile, Lines, Lines) :-
!.
'$lgt_property_location'(_, File, Lines, include(File, Lines)).
% '$lgt_report_singleton_variables'(+compilation_mode, @list, @term, +atom, @pair(integer))
%
% reports the singleton variables found while compiling an entity term in the given mode
'$lgt_report_singleton_variables'(runtime, _, _, _, _).
'$lgt_report_singleton_variables'(compile(_,_,_), Singletons, Term, File, Lines) :-
'$lgt_report_singleton_variables'(Singletons, Term, File, Lines).
% '$lgt_report_singleton_variables'(@list, @term, +atom, @pair(integer))
%
% reports the singleton variables found while compiling an entity term
'$lgt_report_singleton_variables'([], _, _, _).
'$lgt_report_singleton_variables'([Singleton| Singletons], Term, File, Lines) :-
( '$lgt_compiler_flag'(singleton_variables, warning),
'$lgt_filter_singleton_variable_names'([Singleton| Singletons], Term, Names),
Names \== [] ->
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(
warning(singleton_variables),
singleton_variables(File, Lines, Type, Entity, Names, Term)
)
; '$lgt_print_message'(
warning(singleton_variables),
singleton_variables(File, Lines, Names, Term)
)
)
; true
).
% '$lgt_filter_singleton_variable_names'(@list, @term, -list(atom))
%
% filters variables whose name start with an underscore from a singletons list if
% the corresponding compiler flag sets their interpretation to don't care variables
'$lgt_filter_singleton_variable_names'(Singletons, Term, Names) :-
( '$lgt_compiler_flag'(underscore_variables, dont_care) ->
'$lgt_filter_dont_care_variables'(Singletons, SingletonsFiltered)
; SingletonsFiltered = Singletons
),
( '$lgt_pp_parameter_variables_'(ParameterVariables) ->
'$lgt_filter_parameter_variables'(SingletonsFiltered, ParameterVariables, Names)
; Term = (:- Directive),
nonvar(Directive),
'$lgt_logtalk_opening_directive'(Directive) ->
'$lgt_filter_parameter_variables'(SingletonsFiltered, Names)
; '$lgt_singleton_variable_names'(SingletonsFiltered, Names)
).
'$lgt_singleton_variable_names'([], []).
'$lgt_singleton_variable_names'([Name = _| Singletons], [Name| Names]) :-
'$lgt_singleton_variable_names'(Singletons, Names).
'$lgt_filter_dont_care_variables'([], []).
'$lgt_filter_dont_care_variables'([Name = Variable| VariableNames], FilteredVariableNames) :-
( '$lgt_parameter_variable_name'(Name) ->
FilteredVariableNames = [Name = Variable| Rest],
'$lgt_filter_dont_care_variables'(VariableNames, Rest)
; sub_atom(Name, 0, 1, _, '_') ->
'$lgt_filter_dont_care_variables'(VariableNames, FilteredVariableNames)
; FilteredVariableNames = [Name = Variable| Rest],
'$lgt_filter_dont_care_variables'(VariableNames, Rest)
).
'$lgt_filter_parameter_variables'([], _, []).
'$lgt_filter_parameter_variables'([Name = _| VariableNames], ParameterVariables, Names) :-
( '$lgt_member'(Name-_, ParameterVariables) ->
'$lgt_filter_parameter_variables'(VariableNames, ParameterVariables, Names)
; Names = [Name| Rest],
'$lgt_filter_parameter_variables'(VariableNames, ParameterVariables, Rest)
).
'$lgt_filter_parameter_variables'([], []).
'$lgt_filter_parameter_variables'([Name = _| VariableNames], Names) :-
( '$lgt_parameter_variable_name'(Name) ->
'$lgt_filter_parameter_variables'(VariableNames, Names)
; Names = [Name| Rest],
'$lgt_filter_parameter_variables'(VariableNames, Rest)
).
% '$lgt_compiler_error_handler'(+atom, +atom, +pair(integer), @compound)
%
% closes the streams being used for reading and writing terms, restores
% the operator table, reports the compilation error found, and, finally,
% fails in order to abort the compilation process
'$lgt_compiler_error_handler'(SourceFile, ObjectFile, Lines, Error) :-
stream_property(Input, alias(logtalk_compiler_input)),
stream_property(Output, alias(logtalk_compiler_output)), !,
'$lgt_print_message'(error, compiler_error(SourceFile, Lines, Error)),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
catch('$lgt_close'(Input), _, true),
( nonvar(Output) ->
catch('$lgt_close'(Output), _, true),
% try to delete the intermediate Prolog files in order to prevent
% problems by mistaken the broken files by good ones
'$lgt_delete_intermediate_files'(ObjectFile)
; true
),
!,
fail.
% '$lgt_compiler_error_handler'(@compound)
'$lgt_compiler_error_handler'(Error) :-
'$lgt_pp_file_paths_flags_'(_, _, MainSourceFile, ObjectFile, _),
( '$lgt_source_file_context'(SourceFile, Lines) ->
true
; % no file context information available for last term read; likely
% due to a syntax error when trying to read a main file term as syntax
% errors in included files are handled when reading a file to terms
SourceFile = MainSourceFile,
( stream_property(Input, alias(logtalk_compiler_input)),
'$lgt_stream_current_line_number'(Input, Line) ->
Lines = Line-Line
; % some backend Prolog compilers do not support, or do not always support
% (e.g. when a syntax error occurs) querying a stream line number
Lines = '-'(-1, -1)
)
),
'$lgt_compiler_error_handler'(SourceFile, ObjectFile, Lines, Error).
% '$lgt_compiler_first_term_error_handler'(+atom, +pair(integer), @compound)
%
% closes the stream being used for reading, restores the operator table,
% reports the compilation error found, and, finally, fails in order to
% abort the compilation process
'$lgt_compiler_first_term_error_handler'(SourceFile, Lines, Error) :-
( nonvar(Lines) ->
true
; % no line information available likely due to a syntax error
stream_property(Input, alias(logtalk_compiler_input)),
'$lgt_stream_current_line_number'(Input, Line) ->
Lines = Line-Line
; % some backend Prolog compilers do not support, or do not always support
% (e.g. when a syntax error occurs) querying a stream line number
Lines = '-'(-1, -1)
),
'$lgt_print_message'(error, compiler_error(SourceFile, Lines, Error)),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
stream_property(Input, alias(logtalk_compiler_input)),
catch('$lgt_close'(Input), _, true),
!,
fail.
% '$lgt_compiler_output_stream_error_handler'(@stream, @compound)
%
% closes the stream being used for writing compiled terms, restores
% the operator table, reports the compilation error found, and, finally,
% fails in order to abort the compilation process
'$lgt_compiler_output_stream_error_handler'(Stream, Error) :-
'$lgt_print_message'(error, compiler_stream_error(Error)),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
catch('$lgt_close'(Stream), _, true),
!,
fail.
% '$lgt_compiler_stream_error_handler'(@compound)
%
% closes input and output streams if open, restores the operator table,
% reports the compilation error found, and, finally, fails in order to
% abort the compilation process
'$lgt_compiler_stream_error_handler'(Error) :-
( stream_property(Input, alias(logtalk_compiler_input)) ->
catch('$lgt_close'(Input), _, true)
; true
),
( stream_property(Output, alias(logtalk_compiler_output)) ->
catch('$lgt_close'(Output), _, true)
; true
),
'$lgt_print_message'(error, compiler_stream_error(Error)),
'$lgt_restore_global_operator_table',
'$lgt_clean_pp_file_clauses',
'$lgt_clean_pp_entity_clauses',
'$lgt_reset_warnings_counter',
!,
fail.
% '$lgt_read_file_term'(+atom, @stream, -term, @list(var), -pair(integer))
%
% remember term position and variable names in order to support the
% logtalk_load_context/2 predicate and more informative compiler warning
% and error messages
'$lgt_read_file_term'(File, Stream, Term, Singletons, Lines) :-
% we retract first the position and variable names for the previous
% read term as we may get a syntax error while reading the next term;
% this will allow us to use the stream position if necessary to find
% the approximated position of the error
retractall('$lgt_pp_term_source_data_'(_, _, _, _, _)),
% the actual read term predicate is defined in the adapter files as
% there's no standard option for returning the read term position
'$lgt_read_term'(Stream, Term, [variable_names(VariableNames), singletons(Singletons)], Lines),
'$lgt_report_variable_naming_issues'(VariableNames, File, Lines),
assertz('$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines)).
% '$lgt_second_stage'(+atom, @entity_identifier, +compilation_context)
%
% compiler second stage
%
% the first stage collected data on all directives, clause heads, and
% grammar rules heads thus enabling the compilation of initialization/1
% goals and clause body goals
'$lgt_second_stage'(Type, Entity, Ctx) :-
catch(
'$lgt_compile_entity'(Type, Entity, Ctx),
Error,
'$lgt_second_stage_error_handler'(Error)
).
'$lgt_compile_entity'(Type, Entity, Ctx) :-
'$lgt_generate_entity_code'(Type, Ctx),
'$lgt_inline_calls'(Type),
'$lgt_report_lint_issues'(Type, Entity),
'$lgt_write_entity_code'(Type, Entity),
'$lgt_add_entity_source_data'(Type, Entity),
'$lgt_save_entity_runtime_clause'(Type),
'$lgt_restore_file_operator_table',
'$lgt_clean_pp_entity_clauses'(Type).
'$lgt_second_stage_error_handler'(Error) :-
'$lgt_pp_file_paths_flags_'(_, _, _, ObjectFile, _),
% get the source file from the context as we may be reporting
% an error in an included file instead of in the main file
( '$lgt_source_file_context'(SourceFile, Lines) ->
true
; % assume auxiliary clause and thus not part of the source file
'$lgt_pp_file_paths_flags_'(_, _, SourceFile, _, _),
Lines = '-'(0, 0)
),
'$lgt_compiler_error_handler'(SourceFile, ObjectFile, Lines, Error).
% '$lgt_compile_entity_flags'(+atom, -integer)
%
% defines the entity flags value when compiling or dynamically creating a new entity
%
% we use integers in decimal notation instead of binary notation to avoid standards
% compliance issues with some Prolog compilers
'$lgt_compile_entity_flags'(protocol, Flags) :-
( '$lgt_compiler_flag'(debug, on) ->
Debug = 512
; Debug = 0
),
( '$lgt_compiler_flag'(source_data, on) ->
SourceData = 8
; SourceData = 0
),
( '$lgt_pp_dynamic_' ->
Dynamic = 2
; Dynamic = 0
),
( '$lgt_pp_built_in_' ->
BuiltIn = 1
; BuiltIn = 0
),
Flags is Debug + SourceData + Dynamic + BuiltIn.
'$lgt_compile_entity_flags'(category, Flags) :-
( '$lgt_compiler_flag'(debug, on) ->
Debug = 512
; Debug = 0
),
( '$lgt_compiler_flag'(events, allow) ->
Events = 16
; Events = 0
),
( '$lgt_compiler_flag'(source_data, on) ->
SourceData = 8
; SourceData = 0
),
( '$lgt_pp_dynamic_' ->
Dynamic = 2
; Dynamic = 0
),
( '$lgt_pp_built_in_' ->
BuiltIn = 1
; BuiltIn = 0
),
Flags is Debug + Events + SourceData + Dynamic + BuiltIn.
'$lgt_compile_entity_flags'(object, Flags) :-
( '$lgt_pp_module_'(_) ->
Module = 1024
; Module = 0
),
( '$lgt_compiler_flag'(debug, on) ->
Debug = 512
; Debug = 0
),
( '$lgt_compiler_flag'(context_switching_calls, allow) ->
ContextSwitchingCalls = 256
; ContextSwitchingCalls = 0
),
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
DynamicDeclarations = 128
; DynamicDeclarations = 0
),
'$lgt_compiler_flag'(complements, ComplementsFlag),
( ComplementsFlag == deny ->
Complements = 0
; ComplementsFlag == allow ->
Complements = 64
; % ComplementsFlag == restrict,
Complements = 32
),
( '$lgt_compiler_flag'(events, allow) ->
Events = 16
; Events = 0
),
( '$lgt_compiler_flag'(source_data, on) ->
SourceData = 8
; SourceData = 0
),
( '$lgt_pp_threaded_' ->
Threaded = 4
; Threaded = 0
),
( '$lgt_pp_dynamic_' ->
Dynamic = 2
; Dynamic = 0
),
( '$lgt_pp_built_in_' ->
BuiltIn = 1
; BuiltIn = 0
),
Flags is Module + Debug + ContextSwitchingCalls + DynamicDeclarations + Complements + Events + SourceData + Threaded + Dynamic + BuiltIn.
% saves the entity runtime clause after computing the final value of its flags
'$lgt_save_entity_runtime_clause'(object) :-
'$lgt_pp_object_'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, _),
'$lgt_compile_entity_flags'(object, Flags),
assertz('$lgt_pp_runtime_clause_'('$lgt_current_object_'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, Flags))).
'$lgt_save_entity_runtime_clause'(protocol) :-
'$lgt_pp_protocol_'(Ptc, Prefix, Dcl, Rnm, _),
'$lgt_compile_entity_flags'(protocol, Flags),
assertz('$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Ptc, Prefix, Dcl, Rnm, Flags))).
'$lgt_save_entity_runtime_clause'(category) :-
'$lgt_pp_category_'(Ctg, Prefix, Dcl, Def, Rnm, _),
'$lgt_compile_entity_flags'(category, Flags),
assertz('$lgt_pp_runtime_clause_'('$lgt_current_category_'(Ctg, Prefix, Dcl, Def, Rnm, Flags))).
% cleans up all dynamic predicates used during source file compilation
'$lgt_clean_pp_file_clauses' :-
retractall('$lgt_pp_file_initialization_'(_, _)),
retractall('$lgt_pp_file_entity_initialization_'(_, _, _)),
retractall('$lgt_pp_file_encoding_'(_, _, _, _)),
retractall('$lgt_pp_file_bom_'(_, _)),
retractall('$lgt_pp_file_compiler_flag_'(_, _)),
retractall('$lgt_pp_term_source_data_'(_, _, _, _, _)),
% a Logtalk source file may contain only plain Prolog terms
% instead of plain Prolog terms intermixed between entities
% definitions; there might also be plain Prolog terms after
% the last entity definition
retractall('$lgt_pp_prolog_term_'(_, _)),
% retract all file-specific flag values
retractall('$lgt_pp_file_compiler_flag_'(_, _)),
% retract all file-specific term and goal expansion hooks
retractall('$lgt_pp_hook_term_expansion_'(_, _)),
retractall('$lgt_pp_hook_goal_expansion_'(_, _)),
'$lgt_clean_pp_cc_clauses',
'$lgt_clean_pp_runtime_clauses'.
% cleans up all dynamic predicates used for conditional compilation
'$lgt_clean_pp_cc_clauses' :-
retractall('$lgt_pp_cc_if_found_'(_)),
retractall('$lgt_pp_cc_skipping_'),
retractall('$lgt_pp_cc_mode_'(_)).
% cleans up the dynamic predicate used for entity runtime clauses
'$lgt_clean_pp_runtime_clauses' :-
retractall('$lgt_pp_runtime_clause_'(_)).
% cleans up all dynamic predicates used during entity compilation
'$lgt_clean_pp_entity_clauses' :-
'$lgt_clean_pp_object_clauses',
'$lgt_clean_pp_protocol_clauses',
'$lgt_clean_pp_category_clauses'.
'$lgt_clean_pp_entity_clauses'(object) :-
'$lgt_clean_pp_object_clauses'.
'$lgt_clean_pp_entity_clauses'(protocol) :-
'$lgt_clean_pp_protocol_clauses'.
'$lgt_clean_pp_entity_clauses'(category) :-
'$lgt_clean_pp_category_clauses'.
'$lgt_clean_pp_object_clauses' :-
retractall('$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _)),
retractall('$lgt_pp_module_'(_)),
retractall('$lgt_pp_object_initialization_'(_, _, _)),
retractall('$lgt_pp_final_object_initialization_'(_, _)),
retractall('$lgt_pp_imported_category_'(_, _, _, _, _, _)),
retractall('$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _)),
retractall('$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _)),
retractall('$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _)),
retractall('$lgt_pp_threaded_'),
'$lgt_clean_pp_common_object_category_clauses',
'$lgt_clean_pp_common_entity_clauses'.
'$lgt_clean_pp_protocol_clauses' :-
retractall('$lgt_pp_protocol_'(_, _, _, _, _)),
retractall('$lgt_pp_extended_protocol_'(_, _, _, _, _)),
'$lgt_clean_pp_common_entity_clauses'.
'$lgt_clean_pp_category_clauses' :-
retractall('$lgt_pp_category_'(_, _, _, _, _, _)),
retractall('$lgt_pp_complemented_object_'(_, _, _, _, _)),
retractall('$lgt_pp_extended_category_'(_, _, _, _, _, _)),
'$lgt_clean_pp_common_object_category_clauses',
'$lgt_clean_pp_common_entity_clauses'.
'$lgt_clean_pp_common_object_category_clauses' :-
retractall('$lgt_pp_implemented_protocol_'(_, _, _, _, _)),
retractall('$lgt_pp_parameter_variables_'(_)),
retractall('$lgt_pp_object_alias_'(_, _, _, _, _)),
retractall('$lgt_pp_module_alias_'(_, _, _, _, _)),
retractall('$lgt_pp_uses_predicate_'(_, _, _, _, _, _)),
retractall('$lgt_pp_uses_non_terminal_'(_, _, _, _, _, _, _, _)),
retractall('$lgt_pp_use_module_predicate_'(_, _, _, _, _, _)),
retractall('$lgt_pp_use_module_non_terminal_'(_, _, _, _, _, _, _, _)),
retractall('$lgt_pp_def_'(_)),
retractall('$lgt_pp_ddef_'(_)),
retractall('$lgt_pp_super_'(_)),
retractall('$lgt_pp_number_of_clauses_rules_'(_, _, _, _)),
retractall('$lgt_pp_number_of_clauses_rules_'(_, _, _, _, _)),
retractall('$lgt_pp_predicate_definition_location_'(_, _, _, _)),
retractall('$lgt_pp_predicate_definition_location_'(_, _, _, _, _)),
retractall('$lgt_pp_redefined_built_in_'(_, _, _)),
retractall('$lgt_pp_defines_predicate_'(_, _, _, _, _, _)),
retractall('$lgt_pp_inline_predicate_'(_)),
retractall('$lgt_pp_non_tail_recursive_predicate_'(_, _, _, _)),
retractall('$lgt_pp_predicate_recursive_calls_'(_, _, _)),
retractall('$lgt_pp_calls_predicate_'(_, _, _, _, _)),
retractall('$lgt_pp_calls_self_predicate_'(_, _, _, _)),
retractall('$lgt_pp_calls_super_predicate_'(_, _, _, _)),
retractall('$lgt_pp_updates_predicate_'(_, _, _, _)),
retractall('$lgt_pp_non_portable_predicate_'(_, _, _)),
retractall('$lgt_pp_non_portable_function_'(_, _, _)),
retractall('$lgt_pp_missing_function_'(_, _, _)),
retractall('$lgt_pp_missing_meta_predicate_directive_'(_, _, _)),
retractall('$lgt_pp_missing_dynamic_directive_'(_, _, _)),
retractall('$lgt_pp_missing_discontiguous_directive_'(_, _, _)),
retractall('$lgt_pp_missing_multifile_directive_'(_, _, _)),
retractall('$lgt_pp_missing_use_module_directive_'(_, _)),
retractall('$lgt_pp_previous_predicate_'(_, _)),
retractall('$lgt_pp_defines_non_terminal_'(_, _, _)),
retractall('$lgt_pp_calls_non_terminal_'(_, _, _, _)),
retractall('$lgt_pp_referenced_object_'(_, _, _)),
retractall('$lgt_pp_referenced_category_'(_, _, _)),
retractall('$lgt_pp_referenced_module_'(_, _, _)),
retractall('$lgt_pp_referenced_object_message_'(_, _, _, _, _, _)),
retractall('$lgt_pp_referenced_module_predicate_'(_, _, _, _, _, _)).
'$lgt_clean_pp_common_entity_clauses' :-
retractall('$lgt_pp_entity_lines_'(_, _)),
retractall('$lgt_pp_entity_compiler_flag_'(_, _)),
retractall('$lgt_pp_entity_'(_, _, _)),
retractall('$lgt_pp_entity_info_'(_, _, _)),
retractall('$lgt_pp_predicate_info_'(_, _, _, _)),
retractall('$lgt_pp_directive_'(_)),
retractall('$lgt_pp_synchronized_'(_, _, _, _)),
retractall('$lgt_pp_predicate_mutex_counter_'(_)),
retractall('$lgt_pp_public_'(_, _, _, _)),
retractall('$lgt_pp_protected_'(_, _, _, _)),
retractall('$lgt_pp_private_'(_, _, _, _)),
retractall('$lgt_pp_dynamic_'(_, _, _, _)),
retractall('$lgt_pp_discontiguous_'(_, _, _)),
retractall('$lgt_pp_multifile_'(_, _, _, _)),
retractall('$lgt_pp_coinductive_'(_, _, _, _, _, _, _, _, _)),
retractall('$lgt_pp_coinductive_head_'(_, _, _)),
retractall('$lgt_pp_mode_'(_, _, _, _)),
retractall('$lgt_pp_meta_predicate_'(_, _, _, _)),
retractall('$lgt_pp_predicate_alias_'(_, _, _, _, _, _)),
retractall('$lgt_pp_non_terminal_'(_, _, _)),
retractall('$lgt_pp_entity_meta_directive_'(_, _, _)),
retractall('$lgt_pp_dcl_'(_)),
% clean any plain Prolog terms appearing before an entity definition
retractall('$lgt_pp_prolog_term_'(_, _)),
retractall('$lgt_pp_entity_term_'(_, _, _)),
retractall('$lgt_pp_final_entity_term_'(_, _)),
retractall('$lgt_pp_entity_aux_clause_'(_)),
retractall('$lgt_pp_final_entity_aux_clause_'(_)),
retractall('$lgt_pp_predicate_declaration_location_'(_, _, _, _)),
retractall('$lgt_pp_referenced_protocol_'(_, _, _)),
retractall('$lgt_pp_built_in_'),
retractall('$lgt_pp_dynamic_'),
retractall('$lgt_pp_aux_predicate_counter_'(_)).
% '$lgt_clean_lookup_caches'
%
% cleans all entries for all dynamic binding lookup caches
%
% this also have the side-effect of removing the catchall clauses
% that generate the cache entries which we must then re-assert
'$lgt_clean_lookup_caches' :-
retractall('$lgt_send_to_obj_'(_, _, _)),
retractall('$lgt_send_to_obj_ne_'(_, _, _)),
retractall('$lgt_send_to_self_'(_, _, _)),
retractall('$lgt_obj_super_call_'(_, _, _)),
retractall('$lgt_ctg_super_call_'(_, _, _)),
retractall('$lgt_db_lookup_cache_'(_, _, _, _, _)),
'$lgt_reassert_lookup_cache_catchall_clauses'.
% '$lgt_clean_lookup_caches'(@callable)
%
% cleans all entries for a given predicate for all dynamic
% binding lookup caches
%
% this also have the side-effect of removing the catchall clauses
% that generate the cache entries which we must then re-assert
'$lgt_clean_lookup_caches'(Pred) :-
retractall('$lgt_send_to_obj_'(_, Pred, _)),
retractall('$lgt_send_to_obj_ne_'(_, Pred, _)),
retractall('$lgt_send_to_self_'(_, Pred, _)),
retractall('$lgt_obj_super_call_'(_, Pred, _)),
retractall('$lgt_ctg_super_call_'(_, Pred, _)),
retractall('$lgt_db_lookup_cache_'(_, Pred, _, _, _)),
'$lgt_reassert_lookup_cache_catchall_clauses'.
% '$lgt_reassert_lookup_cache_catchall_clauses'
%
% reasserts the catchall clauses for the dynamic binding
% lookup cache predicates that generate the cache entries
'$lgt_reassert_lookup_cache_catchall_clauses' :-
assertz(('$lgt_send_to_obj_'(Obj, Pred, ExCtx) :- '$lgt_send_to_obj_nv'(Obj, Pred, ExCtx))),
assertz(('$lgt_send_to_obj_ne_'(Obj, Pred, ExCtx) :- '$lgt_send_to_obj_ne_nv'(Obj, Pred, ExCtx))),
assertz(('$lgt_send_to_self_'(Obj, Pred, ExCtx) :- '$lgt_send_to_self_nv'(Obj, Pred, ExCtx))),
assertz(('$lgt_obj_super_call_'(Super, Pred, ExCtx) :- '$lgt_obj_super_call_nv'(Super, Pred, ExCtx))),
assertz(('$lgt_ctg_super_call_'(Ctg, Pred, ExCtx) :- '$lgt_ctg_super_call_nv'(Ctg, Pred, ExCtx))),
% support runtime resolved database messages to the "user" pseudo-object
assertz('$lgt_db_lookup_cache_'(user, Clause, _, Clause, true)).
% '$lgt_restore_global_operator_table'
%
% restores the global operator table
%
% called after compiling a source file or after dynamically creating a new entity
'$lgt_restore_global_operator_table' :-
retract('$lgt_pp_entity_operator_'(_, Specifier, Operator, _, _, _)),
op(0, Specifier, Operator),
fail.
'$lgt_restore_global_operator_table' :-
retract('$lgt_pp_file_operator_'(_, Specifier, Operator)),
op(0, Specifier, Operator),
fail.
'$lgt_restore_global_operator_table' :-
retract('$lgt_pp_global_operator_'(Priority, Specifier, Operator)),
op(Priority, Specifier, Operator),
fail.
'$lgt_restore_global_operator_table'.
% '$lgt_restore_file_operator_table'
%
% restores the file operator table
%
% called after compiling a source file entity
'$lgt_restore_file_operator_table' :-
retract('$lgt_pp_entity_operator_'(_, Specifier, Operator, _, _, _)),
op(0, Specifier, Operator),
fail.
'$lgt_restore_file_operator_table' :-
retract('$lgt_pp_file_operator_'(Priority, Specifier, Operator)),
op(Priority, Specifier, Operator),
fail.
'$lgt_restore_file_operator_table'.
% '$lgt_activate_file_operators'(+integer, +operator_specifier, +atom_or_atom_list, +compilation_mode)
%
% activates local file operator definitions
%
% any conflicting global operator is saved so that it can be restored later
'$lgt_activate_file_operators'(_, _, [], _) :-
!.
'$lgt_activate_file_operators'(Priority, Specifier, [Operator| Operators], Mode) :-
!,
'$lgt_activate_file_operator'(Priority, Specifier, Operator, Mode),
'$lgt_activate_file_operators'(Priority, Specifier, Operators, Mode).
'$lgt_activate_file_operators'(Priority, Specifier, Operator, Mode) :-
'$lgt_activate_file_operator'(Priority, Specifier, Operator, Mode).
'$lgt_activate_file_operator'(Priority, Specifier, Operator, compile(_,_,_)) :-
'$lgt_compiler_flag'(redefined_operators, warning),
( '$lgt_iso_spec_operator'(Operator, OriginalSpecifier, OriginalPriority)
; '$lgt_logtalk_spec_operator'(Operator, OriginalSpecifier, OriginalPriority)
),
'$lgt_same_operator_class'(Specifier, OriginalSpecifier),
once((
Priority \== OriginalPriority
; Specifier \== OriginalSpecifier
)),
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(redefined_operators),
redefined_operator(File, Lines, op(OriginalPriority,OriginalSpecifier,Operator), op(Priority,Specifier,Operator))
),
fail.
'$lgt_activate_file_operator'(Priority, Specifier, Operator, _) :-
( current_op(OriginalPriority, OriginalSpecifier, Operator),
'$lgt_same_operator_class'(Specifier, OriginalSpecifier) ->
assertz('$lgt_pp_global_operator_'(OriginalPriority, OriginalSpecifier, Operator))
; true
),
op(Priority, Specifier, Operator),
assertz('$lgt_pp_file_operator_'(Priority, Specifier, Operator)).
% '$lgt_activate_entity_operators'(+integer, +operator_specifier, +atom_or_atom_list, +scope, +atom, +pair(integer), +compilation_mode)
%
% activates local entity operator definitions
%
% any conflicting file operator is saved so that it can be restored later
'$lgt_activate_entity_operators'(_, _, [], _, _, _, _) :-
!.
'$lgt_activate_entity_operators'(Priority, Specifier, [Operator| Operators], Scope, File, Lines, Mode) :-
!,
'$lgt_activate_entity_operator'(Priority, Specifier, Operator, Scope, File, Lines, Mode),
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, Scope, File, Lines, Mode).
'$lgt_activate_entity_operators'(Priority, Specifier, Operator, Scope, File, Lines, Mode) :-
'$lgt_activate_entity_operator'(Priority, Specifier, Operator, Scope, File, Lines, Mode).
'$lgt_activate_entity_operator'(Priority, Specifier, Operator, _, File, Lines, compile(_,_,_)) :-
'$lgt_compiler_flag'(redefined_operators, warning),
( '$lgt_iso_spec_operator'(Operator, OriginalSpecifier, OriginalPriority)
; '$lgt_logtalk_spec_operator'(Operator, OriginalSpecifier, OriginalPriority)
),
'$lgt_same_operator_class'(Specifier, OriginalSpecifier),
once((
Priority \== OriginalPriority
; Specifier \== OriginalSpecifier
)),
'$lgt_pp_entity_'(Type, Entity, _),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(redefined_operators),
redefined_operator(File, Lines, Type, Entity, op(OriginalPriority,OriginalSpecifier,Operator), op(Priority,Specifier,Operator))
),
fail.
'$lgt_activate_entity_operator'(Priority, Specifier, Operator, Scope, File, Lines, _) :-
( current_op(OriginalPriority, OriginalSpecifier, Operator),
'$lgt_same_operator_class'(Specifier, OriginalSpecifier) ->
assertz('$lgt_pp_file_operator_'(OriginalPriority, OriginalSpecifier, Operator))
; true
),
op(Priority, Specifier, Operator),
assertz('$lgt_pp_entity_operator_'(Priority, Specifier, Operator, Scope, File, Lines)),
'$lgt_pp_entity_'(_, Entity, _),
% save entity operator property
( '$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, op(Priority, Specifier, Operator, p(p(p))))) ->
% handle the case where there is already a public declaration for the operator
true
; '$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, op(Priority, Specifier, Operator, Scope))) ->
% duplicated operator declarations may originate from e.g. included files
% or when compiling modules (as objects) that reexport other modules
true
; assertz('$lgt_pp_runtime_clause_'('$lgt_entity_property_'(Entity, op(Priority, Specifier, Operator, Scope))))
).
% '$lgt_expand_file_directive_goal'(+callable, -callable)
%
% expands a file directive goal
%
% used to expand file level initialization/1 goals and conditional
% compilation directive goals (if/1 and elif/1) and deal with some
% special cases
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal) :-
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal, []).
'$lgt_expand_file_directive_goal'(Goal, call(Goal), _) :-
var(Goal),
!.
'$lgt_expand_file_directive_goal'({Goal}, Goal, _) :-
!.
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal, ExpandedGoals) :-
'$lgt_push_if_new'(ExpandedGoals, Goal, NewExpandedGoals),
'$lgt_expand_file_goal'(Goal, ExpandedGoal0),
Goal \== ExpandedGoal0,
!,
'$lgt_expand_file_directive_goal'(ExpandedGoal0, ExpandedGoal, NewExpandedGoals).
'$lgt_expand_file_directive_goal'((Goal1, Goal2), (ExpandedGoal1, ExpandedGoal2), ExpandedGoals) :-
!,
'$lgt_expand_file_directive_goal'(Goal1, ExpandedGoal1, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Goal2, ExpandedGoal2, ExpandedGoals).
'$lgt_expand_file_directive_goal'((IfThen; Else), (TIf -> TThen; TElse), ExpandedGoals) :-
nonvar(IfThen),
IfThen = (If -> Then),
!,
'$lgt_expand_file_directive_goal'(If, TIf, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Then, TThen, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Else, TElse, ExpandedGoals).
'$lgt_expand_file_directive_goal'((IfThen; Else), ('*->'(TIf, TThen); TElse), ExpandedGoals) :-
nonvar(IfThen),
IfThen = '*->'(If, Then),
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_expand_file_directive_goal'(If, TIf, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Then, TThen, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Else, TElse, ExpandedGoals).
'$lgt_expand_file_directive_goal'((Goal1; Goal2), (ExpandedGoal1; ExpandedGoal2), ExpandedGoals) :-
!,
'$lgt_expand_file_directive_goal'(Goal1, ExpandedGoal0, ExpandedGoals),
'$lgt_fix_disjunction_left_side'(ExpandedGoal0, ExpandedGoal1),
'$lgt_expand_file_directive_goal'(Goal2, ExpandedGoal2, ExpandedGoals).
'$lgt_expand_file_directive_goal'('*->'(Goal1, Goal2), '*->'(ExpandedGoal1, ExpandedGoal2), ExpandedGoals) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_expand_file_directive_goal'(Goal1, ExpandedGoal1, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Goal2, ExpandedGoal2, ExpandedGoals).
'$lgt_expand_file_directive_goal'((Goal1 -> Goal2), (ExpandedGoal1 -> ExpandedGoal2), ExpandedGoals) :-
!,
'$lgt_expand_file_directive_goal'(Goal1, ExpandedGoal1, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Goal2, ExpandedGoal2, ExpandedGoals).
'$lgt_expand_file_directive_goal'(\+ Goal, \+ ExpandedGoal, ExpandedGoals) :-
!,
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal, ExpandedGoals).
'$lgt_expand_file_directive_goal'(catch(Goal, Catcher, Recovery), catch(ExpandedGoal, Catcher, ExpandedRecovery), ExpandedGoals) :-
!,
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal, ExpandedGoals),
'$lgt_expand_file_directive_goal'(Recovery, ExpandedRecovery, ExpandedGoals).
% workaround lack of compliance by some backend Prolog compilers
'$lgt_expand_file_directive_goal'(predicate_property(Pred, Prop), '$lgt_predicate_property'(Pred, Prop), _) :-
!.
% expand calls to set_logtalk_flag/2 when possible to avoid the need of runtime type-checking
'$lgt_expand_file_directive_goal'(set_logtalk_flag(Flag, Value), '$lgt_set_compiler_flag'(Flag, Value), _) :-
nonvar(Flag),
nonvar(Value),
!,
'$lgt_check'(read_write_flag, Flag),
'$lgt_check'(flag_value, Flag + Value).
% expand calls to the logtalk_compile/1-2 and logtalk_load/1-2 predicates to
% add a directory argument for default resolving of relative file paths
'$lgt_expand_file_directive_goal'(logtalk_compile(Files), '$lgt_logtalk_compile'(Files, Directory, ExCtx), _) :-
!,
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []).
'$lgt_expand_file_directive_goal'(logtalk_compile(Files, Flags), '$lgt_logtalk_compile'(Files, Flags, Directory, ExCtx), _) :-
!,
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []).
'$lgt_expand_file_directive_goal'(logtalk_load(Files), '$lgt_logtalk_load'(Files, Directory, ExCtx), _) :-
!,
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []).
'$lgt_expand_file_directive_goal'(logtalk_load(Files, Flags), '$lgt_logtalk_load'(Files, Flags, Directory, ExCtx), _) :-
!,
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
'$lgt_execution_context'(ExCtx, user, user, user, user, [], []).
% expand if possible calls to the logtalk_load_context/2 predicate to support
% embedded applications where the compiled code may no longer be loaded using
% the Logtalk runtime
'$lgt_expand_file_directive_goal'(logtalk_load_context(Key, Value), true, _) :-
nonvar(Key),
logtalk_load_context(Key, Value),
!.
% when the directive is found inside an entity, use any applicable uses/2 or
% use_module/2 directive; this is mainly useful when compiling Prolog modules
% as objects as the user can always write a (::)/2 or (:)/2 goal instead
'$lgt_expand_file_directive_goal'(Goal, Obj::Goal, _) :-
'$lgt_pp_entity_'(_, _, _),
'$lgt_pp_uses_predicate_'(Obj, _, Goal, _, _, _),
!.
'$lgt_expand_file_directive_goal'(Goal, ':'(Module,Goal), _) :-
'$lgt_pp_entity_'(_, _, _),
'$lgt_pp_use_module_predicate_'(Module, _, Goal, _, _, _),
!.
% catchall clause
'$lgt_expand_file_directive_goal'(Goal, Goal, _).
% '$lgt_expand_file_goal'(+callable, -callable)
%
% expands a goal; fails if no goal expansion hook is defined
%
% the callers of this predicate must ensure that a goal
% is repeatedly expanded until a fixed-point is reached
%
% the callers must also take care of the case where the
% goal is wrapped with the {}/1 control construct
'$lgt_expand_file_goal'(Goal, ExpandedGoal) :-
( % source-file specific compiler hook
'$lgt_pp_hook_goal_expansion_'(Goal, ExpandedGoal) ->
true
; % default compiler hook
'$lgt_hook_goal_expansion_'(Goal, ExpandedGoal) ->
true
; % dialect specific expansion
'$lgt_prolog_goal_expansion'(Goal, ExpandedGoal) ->
'$lgt_prolog_goal_expansion_portability_warnings'(Goal, ExpandedGoal)
; % no compiler hook defined
fail
),
% the following check means that an expanded goal is checked twice but that
% allows us to distinguish between user errors and goal-expansion errors
'$lgt_check'(callable, ExpandedGoal, goal_expansion(Goal, ExpandedGoal)).
'$lgt_prolog_goal_expansion_portability_warnings'(Goal, ExpandedGoal) :-
( '$lgt_compiler_flag'(portability, warning) ->
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(
warning(portability),
prolog_dialect_goal_expansion(File, Lines, Type, Entity, Goal, ExpandedGoal)
)
; '$lgt_print_message'(
warning(portability),
prolog_dialect_goal_expansion(File, Lines, Goal, ExpandedGoal)
)
)
; true
).
% '$lgt_push_if_new'(@term, @callable, -list)
%
% auxiliary predicate to prevent going into an infinite loop when
% goal-expansion results in a goal that contains the expanded goal
%
% calls to this predicate fail if the goal about to be expanded was
% the result of a previous goal expansion (tested using term equality)
'$lgt_push_if_new'(ExpandedGoals, Pred, NewExpandedGoals) :-
var(ExpandedGoals),
!,
NewExpandedGoals = [Pred].
'$lgt_push_if_new'(ExpandedGoals, Pred, _) :-
'$lgt_member_var'(Pred, ExpandedGoals),
!,
fail.
'$lgt_push_if_new'(ExpandedGoals, Pred, [Pred| ExpandedGoals]).
% '$lgt_compile_include_file_terms'(@list(term), +atom, +compilation_context)
%
% compiles a list of file terms (directives, clauses, or grammar rules)
% found in an included file
'$lgt_compile_include_file_terms'([Term-_| Terms], File, Ctx) :-
'$lgt_pp_cc_skipping_',
% we're performing conditional compilation and skipping terms ...
\+ '$lgt_is_conditional_compilation_directive'(Term),
% ... except for conditional compilation directives
!,
'$lgt_compile_include_file_terms'(Terms, File, Ctx).
'$lgt_compile_include_file_terms'([Term-sd(VariableNames,Singletons,Lines)| Terms], File, Ctx) :-
retractall('$lgt_pp_term_source_data_'(_, _, _, _, _)),
assertz('$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines)),
'$lgt_check'(nonvar, Term, term),
% only the compilation context mode should be shared between different terms
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
'$lgt_comp_ctx'(NewCtx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _),
'$lgt_compile_file_term'(Term, NewCtx),
'$lgt_compile_include_file_terms'(Terms, File, Ctx).
'$lgt_compile_include_file_terms'([], _, _).
% '$lgt_compile_file_term'(@nonvar, +compilation_context)
%
% compiles a source file term (clause, directive, or grammar rule)
%
% we allow non-callable terms to be term-expanded; only if that fails
% we throw an error
'$lgt_compile_file_term'(Term, Ctx) :-
% we must unify any parameter variables used in the term with
% the corresponding entity parameters before any expansion
'$lgt_unify_parameter_variables'(Term, Ctx),
( Term = {_} ->
% bypass control construct; skip term-expansion
'$lgt_compile_expanded_term'(Term, Term, Ctx)
; '$lgt_pp_hook_term_expansion_'(Term, ExpandedTerms) ->
% source-file specific compiler hook
'$lgt_compile_expanded_terms'(ExpandedTerms, Term, Ctx)
; '$lgt_hook_term_expansion_'(Term, ExpandedTerms) ->
% default compiler hook
'$lgt_compile_expanded_terms'(ExpandedTerms, Term, Ctx)
; '$lgt_prolog_term_expansion'(Term, ExpandedTerms) ->
% dialect specific expansion
'$lgt_prolog_term_expansion_portability_warnings'(Term, ExpandedTerms),
'$lgt_compile_expanded_terms'(ExpandedTerms, Term, Ctx)
; % no compiler hook defined
'$lgt_compile_non_expanded_term'(Term, Ctx)
).
'$lgt_prolog_term_expansion_portability_warnings'(Term, ExpandedTerms) :-
( Term \== ExpandedTerms,
'$lgt_compiler_flag'(portability, warning) ->
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(
warning(portability),
prolog_dialect_term_expansion(File, Lines, Type, Entity, Term, ExpandedTerms)
)
; '$lgt_print_message'(
warning(portability),
prolog_dialect_term_expansion(File, Lines, Term, ExpandedTerms)
)
)
; true
).
% '$lgt_compile_expanded_terms'(@list(term), @term, +compilation_context)
% '$lgt_compile_expanded_terms'(@term, @term, +compilation_context)
%
% compiles the expanded terms (which can be a list of terms);
% the second argument is the original term and is used for more
% informative exception terms in case of error
%
% note that the clause order ensures that instantiation errors will be
% caught by the call to the '$lgt_compile_expanded_term'/3 predicate
'$lgt_compile_expanded_terms'([ExpandedTerm| ExpandedTerms], Term, Ctx) :-
!,
'$lgt_compile_expanded_term'(ExpandedTerm, Term, Ctx),
( ExpandedTerm \== (:- end_object),
ExpandedTerm \== (:- end_protocol),
ExpandedTerm \== (:- end_category) ->
% ensure that only the compilation context mode and the entity prefix are
% shared between different terms but keep the current term position
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, _, Mode, _, Lines, _),
'$lgt_comp_ctx'(NewCtx, _, _, _, _, _, _, Prefix, _, _, _, Mode, _, Lines, _)
; % share only the compilation context mode and the current term position
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _),
'$lgt_comp_ctx'(NewCtx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _)
),
'$lgt_compile_expanded_terms'(ExpandedTerms, Term, NewCtx).
'$lgt_compile_expanded_terms'([], _, _) :-
!.
'$lgt_compile_expanded_terms'(ExpandedTerm, Term, Ctx) :-
'$lgt_compile_expanded_term'(ExpandedTerm, Term, Ctx).
% '$lgt_compile_expanded_term'(@term, @term, +compilation_context)
%
% compiles a source file term (a clause, directive, or grammar rule);
% the second argument is the original term and is used for more
% informative exception terms in case of error
'$lgt_compile_expanded_term'((-), Term, _) :-
% catch variables
throw(error(instantiation_error, term_expansion(Term, _))).
'$lgt_compile_expanded_term'(begin_of_file, _, _) :-
!.
'$lgt_compile_expanded_term'(end_of_file, _, Ctx) :-
'$lgt_pp_module_'(Module),
!,
% module definitions start with an opening module/1-2 directive and are assumed
% to end at the end of a source file; there is no module closing directive; set
% the initial compilation context and the position for compiling the end_of_file term
'$lgt_pp_referenced_object_'(Module, _, Start-_),
'$lgt_comp_ctx_lines'(Ctx, _-End),
assertz('$lgt_pp_entity_lines_'(Module, Start-End)),
'$lgt_second_stage'(object, Module, Ctx),
'$lgt_print_message'(silent(compiling), compiled_entity(module, Module)).
'$lgt_compile_expanded_term'(end_of_file, Term, _) :-
'$lgt_pp_entity_'(Type, _, _),
% unexpected end-of-file while compiling an entity
( Type == object ->
throw(error(existence_error(directive, end_object/0), term_expansion(Term, end_of_file)))
; Type == protocol ->
throw(error(existence_error(directive, end_protocol/0), term_expansion(Term, end_of_file)))
; % Type == category,
throw(error(existence_error(directive, end_category/0), term_expansion(Term, end_of_file)))
).
'$lgt_compile_expanded_term'(end_of_file, Term, _) :-
'$lgt_pp_cc_if_found_'(_),
% unexpected end-of-file while compiling a conditional compilation block
throw(error(existence_error(directive, endif/0), term_expansion(Term, end_of_file))).
'$lgt_compile_expanded_term'(end_of_file, _, _) :-
!.
'$lgt_compile_expanded_term'({ExpandedTerm}, Term, _) :-
% bypass control construct; expanded term is final
!,
( callable(ExpandedTerm) ->
( '$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines) ->
SourceData = sd(Term, VariableNames, Singletons, File, Lines)
; SourceData = nil, Lines = '-'(-1, -1)
),
( '$lgt_pp_entity_'(_, _, _) ->
% ensure that the relative order of the entity terms is kept
assertz('$lgt_pp_entity_term_'({ExpandedTerm}, SourceData, Lines))
; % non-entity terms
assertz('$lgt_pp_prolog_term_'(ExpandedTerm, Lines))
)
; var(ExpandedTerm) ->
throw(error(instantiation_error, term_expansion(Term, {ExpandedTerm})))
; throw(error(type_error(callable, Term), term_expansion(Term, {ExpandedTerm})))
).
'$lgt_compile_expanded_term'((Head :- Body), _, Ctx) :-
!,
'$lgt_comp_ctx_term'(Ctx, (Head :- Body)),
'$lgt_compile_clause'((Head :- Body), Ctx).
'$lgt_compile_expanded_term'((:- Directive), _, Ctx) :-
!,
'$lgt_comp_ctx_term'(Ctx, (:- Directive)),
'$lgt_compile_directive'(Directive, Ctx).
'$lgt_compile_expanded_term'((Head --> Body), _, Ctx) :-
!,
'$lgt_comp_ctx_term'(Ctx, (Head --> Body)),
'$lgt_compile_grammar_rule'((Head --> Body), Ctx).
'$lgt_compile_expanded_term'(ExpandedTerm, Term, Ctx) :-
( callable(ExpandedTerm) ->
% fact
'$lgt_comp_ctx_term'(Ctx, ExpandedTerm),
'$lgt_compile_clause'(ExpandedTerm, Ctx)
; throw(error(type_error(callable, ExpandedTerm), term_expansion(Term, ExpandedTerm)))
).
% '$lgt_compile_non_expanded_term'(@nonvar, +compilation_context)
%
% compiles a source file term (a clause, directive, or grammar rule);
% the second argument is the original term and is used for more
% informative exception terms in case of error
'$lgt_compile_non_expanded_term'(begin_of_file, _) :-
!.
'$lgt_compile_non_expanded_term'(end_of_file, Ctx) :-
'$lgt_pp_module_'(Module),
!,
% module definitions start with an opening module/1-2 directive and are assumed
% to end at the end of a source file; there is no module closing directive; set
% the initial compilation context and the position for compiling the end_of_file term
'$lgt_pp_referenced_object_'(Module, _, Start-_),
'$lgt_comp_ctx_lines'(Ctx, _-End),
assertz('$lgt_pp_entity_lines_'(Module, Start-End)),
'$lgt_second_stage'(object, Module, Ctx),
'$lgt_print_message'(silent(compiling), compiled_entity(module, Module)).
'$lgt_compile_non_expanded_term'(end_of_file, _) :-
'$lgt_pp_entity_'(Type, _, _),
% unexpected end-of-file while compiling an entity
( Type == object ->
throw(error(existence_error(directive, end_object/0), term(end_of_file)))
; Type == protocol ->
throw(error(existence_error(directive, end_protocol/0), term(end_of_file)))
; % Type == category,
throw(error(existence_error(directive, end_category/0), term(end_of_file)))
).
'$lgt_compile_non_expanded_term'(end_of_file, _) :-
'$lgt_pp_cc_if_found_'(_),
% unexpected end-of-file while compiling a conditional compilation block
throw(error(existence_error(directive, endif/0), term(end_of_file))).
'$lgt_compile_non_expanded_term'(end_of_file, _) :-
!.
'$lgt_compile_non_expanded_term'({Term}, _) :-
% bypass control construct; term is final
!,
( callable(Term) ->
( '$lgt_pp_term_source_data_'({Term}, VariableNames, Singletons, File, Lines) ->
SourceData = sd(Term, VariableNames, Singletons, File, Lines)
; SourceData = nil, Lines = '-'(-1, -1)
),
( '$lgt_pp_entity_'(_, _, _) ->
% ensure that the relative order of the entity terms is kept
assertz('$lgt_pp_entity_term_'({Term}, SourceData, Lines))
; % non-entity terms
assertz('$lgt_pp_prolog_term_'(Term, Lines))
)
; var(Term) ->
throw(error(instantiation_error, term({Term})))
; throw(error(type_error(callable, Term), term({Term})))
).
'$lgt_compile_non_expanded_term'((Head :- Body), Ctx) :-
!,
'$lgt_comp_ctx_term'(Ctx, (Head :- Body)),
'$lgt_compile_clause'((Head :- Body), Ctx).
'$lgt_compile_non_expanded_term'((:- Directive), Ctx) :-
!,
'$lgt_comp_ctx_term'(Ctx, (:- Directive)),
'$lgt_compile_directive'(Directive, Ctx).
'$lgt_compile_non_expanded_term'((Head --> Body), Ctx) :-
!,
'$lgt_comp_ctx_term'(Ctx, (Head --> Body)),
'$lgt_compile_grammar_rule'((Head --> Body), Ctx).
'$lgt_compile_non_expanded_term'(Term, Ctx) :-
( callable(Term) ->
'$lgt_compile_clause'(Term, Ctx)
; throw(error(type_error(callable, Term), term(Term)))
).
% '$lgt_compile_runtime_include_file_terms'(@list(term), +atom)
%
% compiles a list of runtime terms (clauses, directives, or grammar rules)
% found in an included file
%
% note that the clause order ensures that instantiation errors will be caught
% by the call to the '$lgt_compile_runtime_term'/2 predicate
'$lgt_compile_runtime_include_file_terms'([Term-_| Terms], File) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, runtime, _, '-'(-1, -1), _),
'$lgt_compile_runtime_term'(Term, Ctx),
'$lgt_compile_runtime_include_file_terms'(Terms, File).
'$lgt_compile_runtime_include_file_terms'([], _).
% '$lgt_compile_runtime_terms'(@list(term))
%
% compiles a list of runtime terms (clauses, directives, or grammar rules)
%
% note that the clause order ensures that instantiation errors will be caught
% by the call to the '$lgt_compile_runtime_term'/2 predicate
'$lgt_compile_runtime_terms'([Term| Terms]) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, runtime, _, '-'(-1, -1), _),
'$lgt_compile_runtime_term'(Term, Ctx),
'$lgt_compile_runtime_terms'(Terms).
'$lgt_compile_runtime_terms'([]).
% '$lgt_compile_runtime_term'(@term, +compilation_context)
%
% compiles a runtime term (a clause, directive, or grammar rule)
'$lgt_compile_runtime_term'((-), _) :-
% catch variables
throw(error(instantiation_error, term)).
'$lgt_compile_runtime_term'(begin_of_file, _) :-
!.
'$lgt_compile_runtime_term'(end_of_file, _) :-
!.
'$lgt_compile_runtime_term'({Term}, _) :-
% bypass control construct; term is final
!,
( callable(Term) ->
assertz('$lgt_pp_entity_term_'({Term}, nil, '-'(-1, -1)))
; var(Term) ->
throw(error(instantiation_error, term({Term})))
; throw(error(type_error(callable, Term), term({Term})))
).
'$lgt_compile_runtime_term'((Head :- Body), Ctx) :-
!,
'$lgt_compile_clause'((Head :- Body), Ctx).
'$lgt_compile_runtime_term'((:- Directive), Ctx) :-
!,
'$lgt_compile_directive'(Directive, Ctx).
'$lgt_compile_runtime_term'((Head --> Body), Ctx) :-
!,
'$lgt_compile_grammar_rule'((Head --> Body), Ctx).
'$lgt_compile_runtime_term'(Term, _) :-
\+ callable(Term),
throw(error(type_error(callable, Term), term(Term))).
'$lgt_compile_runtime_term'(Term, Ctx) :-
% fact
'$lgt_compile_clause'(Term, Ctx).
% '$lgt_compile_directive'(@term, +compilation_context)
%
% compiles a directive
'$lgt_compile_directive'((-), _) :-
% catch variables
throw(error(instantiation_error, directive(_))).
% conditional compilation directives
'$lgt_compile_directive'(if(Goal), Ctx) :-
( Goal = {UserGoal} ->
% final goal
'$lgt_check'(callable, UserGoal, directive(if(Goal))),
fail
; '$lgt_check'(callable, Goal, directive(if(Goal))),
% only expand goals when compiling a source file
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal),
Goal \== ExpandedGoal,
!,
'$lgt_compile_directive'(if({ExpandedGoal}), Ctx)
).
'$lgt_compile_directive'(if(Goal), _) :-
'$lgt_pp_cc_mode_'(Value),
% not top-level if/1 directive
!,
asserta('$lgt_pp_cc_if_found_'(Goal)),
( Value == ignore ->
% another if ... endif to ignore
asserta('$lgt_pp_cc_mode_'(ignore))
; Value == seek_else ->
% we're looking for an else; ignore this if ... endif
asserta('$lgt_pp_cc_mode_'(ignore))
; Value == skip_all ->
asserta('$lgt_pp_cc_mode_'(ignore))
; % Value == skip_else,
( ( Goal = {UserGoal} ->
catch(UserGoal, Error, '$lgt_compiler_error_handler'(Error))
; catch(Goal, Error, '$lgt_compiler_error_handler'(Error))
) ->
asserta('$lgt_pp_cc_mode_'(skip_else))
; asserta('$lgt_pp_cc_mode_'(seek_else)),
retractall('$lgt_pp_cc_skipping_'),
assertz('$lgt_pp_cc_skipping_')
)
).
'$lgt_compile_directive'(if(Goal), _) :-
% top-level if
!,
asserta('$lgt_pp_cc_if_found_'(Goal)),
( ( Goal = {UserGoal} ->
catch(UserGoal, Error, '$lgt_compiler_error_handler'(Error))
; catch(Goal, Error, '$lgt_compiler_error_handler'(Error))
) ->
asserta('$lgt_pp_cc_mode_'(skip_else))
; asserta('$lgt_pp_cc_mode_'(seek_else)),
retractall('$lgt_pp_cc_skipping_'),
assertz('$lgt_pp_cc_skipping_')
).
'$lgt_compile_directive'(elif(Goal), _) :-
\+ '$lgt_pp_cc_if_found_'(_),
throw(error(existence_error(directive, if/1), directive(elif(Goal)))).
'$lgt_compile_directive'(elif(Goal), Ctx) :-
( Goal = {UserGoal} ->
% final goal
'$lgt_check'(callable, UserGoal, directive(elif(Goal))),
fail
; '$lgt_check'(callable, Goal, directive(elif(Goal))),
% only expand goals when compiling a source file
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal),
Goal \== ExpandedGoal,
!,
'$lgt_compile_directive'(elif({ExpandedGoal}), Ctx)
).
'$lgt_compile_directive'(elif(Goal), _) :-
'$lgt_pp_cc_mode_'(Mode),
( Mode == ignore ->
% we're inside an if ... endif that we're ignoring
true
; Mode == skip_else ->
% the corresponding if is true so we must skip this elif
retractall('$lgt_pp_cc_skipping_'),
assertz('$lgt_pp_cc_skipping_'),
retract('$lgt_pp_cc_mode_'(_)),
asserta('$lgt_pp_cc_mode_'(skip_all))
; Mode == skip_all ->
true
; % Mode == seek_else,
% the corresponding if is false
retract('$lgt_pp_cc_mode_'(_)),
( ( Goal = {UserGoal} ->
catch(UserGoal, Error, '$lgt_compiler_error_handler'(Error))
; catch(Goal, Error, '$lgt_compiler_error_handler'(Error))
) ->
retractall('$lgt_pp_cc_skipping_'),
asserta('$lgt_pp_cc_mode_'(skip_else))
; asserta('$lgt_pp_cc_mode_'(seek_else))
)
),
!.
'$lgt_compile_directive'(else, _) :-
\+ '$lgt_pp_cc_if_found_'(_),
throw(error(existence_error(directive, if/1), directive(else))).
'$lgt_compile_directive'(else, _) :-
'$lgt_pp_cc_mode_'(Mode),
( Mode == ignore ->
% we're inside an if ... endif that we're ignoring
true
; Mode == skip_else ->
% the corresponding if is true so we must skip this else
% and any enclose if ... endif
retractall('$lgt_pp_cc_skipping_'),
assertz('$lgt_pp_cc_skipping_'),
retract('$lgt_pp_cc_mode_'(_)),
asserta('$lgt_pp_cc_mode_'(skip_all))
; Mode == skip_all ->
true
; % Mode == seek_else ->
% the corresponding if is false
retract('$lgt_pp_cc_mode_'(_)),
asserta('$lgt_pp_cc_mode_'(compile)),
retractall('$lgt_pp_cc_skipping_')
),
!.
'$lgt_compile_directive'(endif, _) :-
\+ '$lgt_pp_cc_if_found_'(_),
throw(error(existence_error(directive, if/1), directive(endif))).
'$lgt_compile_directive'(endif, _) :-
retract('$lgt_pp_cc_if_found_'(_)),
retract('$lgt_pp_cc_mode_'(Mode)),
( Mode \== ignore ->
retractall('$lgt_pp_cc_skipping_')
; \+ '$lgt_pp_cc_if_found_'(_) ->
retractall('$lgt_pp_cc_skipping_'),
retractall('$lgt_pp_cc_mode_'(_))
; true
),
!.
% remaining directives
'$lgt_compile_directive'(Directive, Ctx) :-
\+ '$lgt_pp_entity_'(_, _, _),
% not compiling an entity
\+ '$lgt_logtalk_opening_directive'(Directive),
% directive occurs before opening entity directive
!,
( '$lgt_logtalk_closing_directive'(Directive) ->
% closing entity directive occurs before the opening entity directive;
% the opening directive is probably missing or misspelt
( Directive == end_object ->
throw(error(existence_error(directive, object/1), directive(Directive)))
; Directive == end_protocol ->
throw(error(existence_error(directive, protocol/1), directive(Directive)))
; % Directive == end_category ->
throw(error(existence_error(directive, category/1), directive(Directive)))
)
; % compile it as a source file-level directive
catch(
'$lgt_compile_file_directive'(Directive, Ctx),
Error,
throw(error(Error, directive(Directive)))
)
).
'$lgt_compile_directive'(Directive, Ctx) :-
'$lgt_logtalk_directive'(Directive),
!,
catch(
'$lgt_compile_logtalk_directive'(Directive, Ctx),
Error,
throw(error(Error, directive(Directive)))
).
'$lgt_compile_directive'(Directive, Ctx) :-
'$lgt_prolog_meta_directive'(Directive, Meta),
% as defined in the Prolog adapter files
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
compiling_proprietary_prolog_directive(File, Lines, Type, Entity, Directive)
)
; true
),
% save the source data information for use in the second compiler stage
% (where it might be required by calls to the logtalk_load_context/2
% predicate during goal expansion)
( '$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines) ->
SourceData = sd(Term, VariableNames, Singletons, File, Lines)
; SourceData = nil, Lines = '-'(-1, -1)
),
assertz('$lgt_pp_entity_meta_directive_'(directive(Directive, Meta), SourceData, Lines)).
'$lgt_compile_directive'(Directive, Ctx) :-
'$lgt_pp_module_'(Current),
% we're compiling a module as an object
Directive \= use_module(_),
Directive \= ensure_loaded(_),
% but not unsupported directives that the backend Prolog compiler adapter
% file failed to expand into supported use_module/2 directives
( '$lgt_pp_defines_predicate_'(Directive, _, _, _, _, _)
; '$lgt_pp_uses_predicate_'(_, _, Directive, _, _, _)
% directive is a query for a locally defined predicate
; '$lgt_pp_use_module_predicate_'(_, _, Directive, _, _, _)
% or a predicate referenced in a use_module/2 directive
; '$lgt_built_in_predicate'(Directive)
% or a built-in predicate
; \+ '$lgt_control_construct'(Directive),
'$lgt_find_visible_module_predicate'(Current, Module, Directive),
% or an implicit call to a module predicate with a missing use_module/2 directive;
% in practice, this only occurs in backend systems with an autoload mechanism
functor(Directive, Functor, Arity),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_remember_missing_use_module_directive'(Mode, Module, Functor/Arity)
),
!,
% compile query as an initialization goal
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
compiling_query_as_initialization_goal(File, Lines, Type, Entity, Directive)
)
; true
),
'$lgt_compile_logtalk_directive'(initialization(Directive), Ctx).
'$lgt_compile_directive'(encoding(Encoding), Ctx) :-
'$lgt_source_file_context'(Path, _),
'$lgt_pp_runtime_clause_'('$lgt_included_file_'(Path, _, _, _)),
% encoding/1 directives may be used in included
% files but not as entity directives
!,
'$lgt_compile_file_directive'(encoding(Encoding), Ctx).
'$lgt_compile_directive'(Directive, _) :-
functor(Directive, Functor, Arity),
throw(error(domain_error(directive, Functor/Arity), directive(Directive))).
% '$lgt_compile_file_directive'(@nonvar, +compilation_context)
%
% compiles file-level directives, i.e. directives that are not encapsulated in a Logtalk
% entity; error-checking is delegated in most cases to the backend Prolog compiler
'$lgt_compile_file_directive'(encoding(Encoding), Ctx) :-
!,
'$lgt_source_file_context'(File, Lines),
( '$lgt_pp_file_encoding_'(File, Encoding, _, Line),
% encoding/1 directive already found and processed ...
'$lgt_comp_ctx_lines'(Ctx, Line-_) ->
% ... same encoding/1 directive that was found and processed
true
; % out-of-place encoding/1 directive, which must be the first term in a source file
'$lgt_compiler_flag'(encodings, silent) ->
true
; '$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(encodings), ignored_encoding_directive(File, Lines))
).
'$lgt_compile_file_directive'(ensure_loaded(FileSpec), _) :-
!,
% perform basic error checking
'$lgt_check'(ground, FileSpec),
% try to expand the file spec as the directive may be found in an included file
'$lgt_expand_module_file_specification'(FileSpec, ExpandedFile),
% try to call ensure_loaded/1 as a built-in predicate but ignore any errors
catch(ensure_loaded(ExpandedFile), _, true),
'$lgt_pp_term_source_data_'(_, _, _, _, Lines),
assertz('$lgt_pp_prolog_term_'((:- ensure_loaded(ExpandedFile)), Lines)).
'$lgt_compile_file_directive'(use_module(FileSpec), _) :-
'$lgt_prolog_feature'(modules, unsupported),
throw(error(domain_error(directive, use_module/1), directive(use_module(FileSpec)))).
'$lgt_compile_file_directive'(use_module(FileSpec), _) :-
!,
% perform basic error checking
'$lgt_check'(ground, FileSpec),
% try to expand the file spec as the directive may be found in an included file
'$lgt_expand_module_file_specification'(FileSpec, ExpandedFile),
% try to call use_module/1 as a built-in predicate but ignore any errors
catch(use_module(ExpandedFile), _, true),
'$lgt_pp_term_source_data_'(_, _, _, _, Lines),
assertz('$lgt_pp_prolog_term_'((:- use_module(ExpandedFile)), Lines)).
'$lgt_compile_file_directive'(use_module(FileSpec, Imports), _) :-
'$lgt_prolog_feature'(modules, unsupported),
throw(error(domain_error(directive, use_module/2), directive(use_module(FileSpec, Imports)))).
'$lgt_compile_file_directive'(use_module(FileSpec, Imports), _) :-
!,
% perform basic error checking
'$lgt_check'(ground, FileSpec),
'$lgt_check'(ground, Imports),
% try to expand the file spec as the directive may be found in an included file
'$lgt_expand_module_file_specification'(FileSpec, ExpandedFile),
% try to call use_module/2 as a built-in predicate but ignore any errors
catch(use_module(ExpandedFile, Imports), _, true),
'$lgt_pp_term_source_data_'(_, _, _, _, Lines),
assertz('$lgt_pp_prolog_term_'((:- use_module(ExpandedFile, Imports)), Lines)).
% handling of this Prolog directive is necessary to
% support the Logtalk term-expansion mechanism
'$lgt_compile_file_directive'(include(File), Ctx) :-
!,
% read the file terms for compilation
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_read_file_to_terms'(File, Directory, Path, Terms, Mode),
% save the dependency in the main file to support make
'$lgt_pp_file_paths_flags_'(MainBasename, MainDirectory, _, _, _),
'$lgt_file_modification_time'(Path, TimeStamp),
assertz('$lgt_pp_runtime_clause_'('$lgt_included_file_'(Path, MainBasename, MainDirectory, TimeStamp))),
% save loading stack to deal with failed compilation
retractall('$lgt_file_loading_stack_'(Path, Directory)),
asserta('$lgt_file_loading_stack_'(Path, Directory)),
% compile the included file terms
catch(
'$lgt_compile_include_file_terms'(Terms, Path, Ctx),
Error,
(retract('$lgt_file_loading_stack_'(Path, Directory)), throw(Error))
),
retractall('$lgt_file_loading_stack_'(Path, Directory)).
'$lgt_compile_file_directive'(initialization(Goal), Ctx) :-
!,
% perform basic error checking
'$lgt_check'(callable, Goal),
% initialization directives are collected and moved to the end of file
% to minimize compatibility issues with backend Prolog compilers
'$lgt_source_file_context'(_File, Lines),
( Goal = {UserGoal} ->
% final goal
'$lgt_check'(callable, UserGoal),
assertz('$lgt_pp_file_initialization_'(Goal, Lines))
; '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
% goals are only expanded when compiling a source file
'$lgt_expand_file_directive_goal'(Goal, ExpandedGoal),
Goal \== ExpandedGoal ->
assertz('$lgt_pp_file_initialization_'(ExpandedGoal, Lines))
; assertz('$lgt_pp_file_initialization_'(Goal, Lines))
).
'$lgt_compile_file_directive'(op(Priority, Specifier, Operators), Ctx) :-
!,
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_activate_file_operators'(Priority, Specifier, Operators, Mode),
'$lgt_pp_term_source_data_'(_, _, _, _, Lines),
assertz('$lgt_pp_prolog_term_'((:- op(Priority, Specifier, Operators)), Lines)).
'$lgt_compile_file_directive'(set_logtalk_flag(Name, Value), _) :-
!,
'$lgt_check'(read_write_flag, Name),
'$lgt_check'(flag_value, Name+Value),
% local scope (restricted to the source file being compiled)
Flag =.. [Name, Value],
'$lgt_set_compiler_flags'([Flag]).
'$lgt_compile_file_directive'(set_prolog_flag(Flag, Value), Ctx) :-
!,
% perform basic error and portability checking
'$lgt_compile_body'(set_prolog_flag(Flag, Value), _, _, _, Ctx),
% require a bound value
'$lgt_check'(nonvar, Value),
% setting the flag during compilation may or may not work as expected
% depending on the flag and on the backend Prolog compiler
set_prolog_flag(Flag, Value),
% we also copy the directive to the generated intermediate Prolog file
'$lgt_pp_term_source_data_'(_, _, _, _, Lines),
assertz('$lgt_pp_prolog_term_'((:- set_prolog_flag(Flag, Value)), Lines)).
'$lgt_compile_file_directive'(multifile(Preds), _) :-
% perform basic error checking
'$lgt_flatten_to_list'(Preds, PredsFlatted),
'$lgt_check_file_predicate_directive_arguments'(PredsFlatted, (multifile)),
fail.
'$lgt_compile_file_directive'(dynamic(Preds), _) :-
% perform basic error checking
'$lgt_flatten_to_list'(Preds, PredsFlatted),
'$lgt_check_file_predicate_directive_arguments'(PredsFlatted, (dynamic)),
fail.
'$lgt_compile_file_directive'(discontiguous(Preds), _) :-
% perform basic error checking
'$lgt_flatten_to_list'(Preds, PredsFlatted),
'$lgt_check_file_predicate_directive_arguments'(PredsFlatted, (discontiguous)),
fail.
'$lgt_compile_file_directive'(Directive, Ctx) :-
'$lgt_logtalk_built_in_predicate'(Directive, _),
% Logtalk built-in predicate being used as a directive
!,
% directive will be copied to the generated Prolog file
'$lgt_pp_term_source_data_'(_, _, _, File, Lines),
assertz('$lgt_pp_prolog_term_'((:- Directive), Lines)),
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(portability), logtalk_built_in_predicate_as_directive(File, Lines, Directive))
; true
).
'$lgt_compile_file_directive'(Directive, Ctx) :-
( Directive = {_}
; Directive = [_| _]
),
% assume Logtalk or Prolog top-level shortcut being used as a directive
!,
% directive will be copied to the generated Prolog file
'$lgt_pp_term_source_data_'(_, _, _, File, Lines),
assertz('$lgt_pp_prolog_term_'((:- Directive), Lines)),
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(portability), top_level_shortcut_as_directive(File, Lines, Directive))
; true
).
'$lgt_compile_file_directive'(Directive, Ctx) :-
% directive will be copied to the generated Prolog file
'$lgt_pp_term_source_data_'(_, _, _, File, Lines),
assertz('$lgt_pp_prolog_term_'((:- Directive), Lines)),
% report a possible portability issue if warranted
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning),
\+ '$lgt_file_directive'(Directive) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(portability), non_standard_file_directive(File, Lines, Directive))
; true
).
% auxiliary predicate for performing basic error checking of file level
% predicate directive arguments
'$lgt_check_file_predicate_directive_arguments'([Pred| Preds], Property) :-
!,
'$lgt_check_file_predicate_directive_argument'(Pred, Property),
'$lgt_check_file_predicate_directive_arguments'(Preds, Property).
'$lgt_check_file_predicate_directive_arguments'([], _).
'$lgt_check_file_predicate_directive_argument'(Obj::Pred, Property) :-
% Logtalk entity predicates must be defined within an entity but be
% sure there aren't instantiation or type errors in the directive
!,
'$lgt_check'(object_identifier, Obj),
'$lgt_check'(predicate_or_non_terminal_indicator, Pred),
throw(permission_error(declare, Property, Obj::Pred)).
'$lgt_check_file_predicate_directive_argument'(':'(Module,Pred), _) :-
!,
'$lgt_check'(module_identifier, Module),
'$lgt_check'(predicate_or_non_terminal_indicator, Pred).
'$lgt_check_file_predicate_directive_argument'(Pred, _) :-
'$lgt_check'(predicate_or_non_terminal_indicator, Pred).
'$lgt_expand_module_file_specification'(FileSpec, ExpandedFile) :-
( atom(FileSpec),
% try to expand to an existing Prolog file
'$lgt_source_file_name'(FileSpec, [], _, _, Extension, ExpandedFile),
'$lgt_file_extension'(prolog, Extension),
'$lgt_file_exists'(ExpandedFile) ->
true
; % otherwise try the file spec as-is
ExpandedFile = FileSpec
).
% '$lgt_compile_logtalk_directives'(+list(term), +compilation_context)
%
% compiles a list of Logtalk directives when dynamically creating an entity
'$lgt_compile_logtalk_directives'([Directive| Directives], Ctx) :-
( var(Directive) ->
throw(instantiation_error)
; '$lgt_logtalk_directive'(Directive) ->
'$lgt_compile_logtalk_directive'(Directive, Ctx),
% only the compilation context mode and lines should be shared between different directives
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _),
'$lgt_comp_ctx'(NewCtx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _),
'$lgt_compile_logtalk_directives'(Directives, NewCtx)
; '$lgt_prolog_meta_directive'(Directive, _) ->
'$lgt_compile_directive'(Directive, Ctx)
; functor(Directive, Functor, Arity),
throw(domain_error(directive, Functor/Arity))
).
'$lgt_compile_logtalk_directives'([], _).
% '$lgt_compile_logtalk_directive'(@term, +compilation_context)
%
% compiles a Logtalk directive and its (possibly empty) list of arguments
'$lgt_compile_logtalk_directive'((-), _) :-
% catch variables
throw(instantiation_error).
'$lgt_compile_logtalk_directive'(include(File), Ctx) :-
% read the file terms for compilation
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_read_file_to_terms'(File, Directory, Path, Terms, Mode),
% save the dependency in the main file to support make if compiling a source file
( Mode == runtime ->
true
; '$lgt_pp_file_paths_flags_'(MainBasename, MainDirectory, _, _, _),
'$lgt_file_modification_time'(Path, TimeStamp),
assertz('$lgt_pp_runtime_clause_'('$lgt_included_file_'(Path, MainBasename, MainDirectory, TimeStamp)))
),
% save loading stack to deal with failed compilation
retractall('$lgt_file_loading_stack_'(Path, Directory)),
asserta('$lgt_file_loading_stack_'(Path, Directory)),
% compile the included file terms
catch(
( Mode == runtime ->
'$lgt_compile_runtime_include_file_terms'(Terms, Path)
; '$lgt_compile_include_file_terms'(Terms, Path, Ctx)
),
Error,
(retract('$lgt_file_loading_stack_'(Path, Directory)), throw(Error))
),
retractall('$lgt_file_loading_stack_'(Path, Directory)).
% object opening and closing directives
'$lgt_compile_logtalk_directive'(object(Obj), Ctx) :-
'$lgt_compile_logtalk_directive'(object_(Obj, []), Ctx).
'$lgt_compile_logtalk_directive'(object(Obj, Relation), Ctx) :-
'$lgt_compile_logtalk_directive'(object_(Obj, [Relation]), Ctx).
'$lgt_compile_logtalk_directive'(object(Obj, Relation1, Relation2), Ctx) :-
'$lgt_compile_logtalk_directive'(object_(Obj, [Relation1, Relation2]), Ctx).
'$lgt_compile_logtalk_directive'(object(Obj, Relation1, Relation2, Relation3), Ctx) :-
'$lgt_compile_logtalk_directive'(object_(Obj, [Relation1, Relation2, Relation3]), Ctx).
'$lgt_compile_logtalk_directive'(object(Obj, Relation1, Relation2, Relation3, Relation4), Ctx) :-
'$lgt_compile_logtalk_directive'(object_(Obj, [Relation1, Relation2, Relation3, Relation4]), Ctx).
% auxiliary predicate to compile all variants to the object opening directive
'$lgt_compile_logtalk_directive'(object_(Obj, Relations), Ctx) :-
( var(Obj) ->
throw(instantiation_error)
; \+ callable(Obj) ->
throw(type_error(object_identifier, Obj))
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _)) ->
% an object with the same identifier was defined earlier in the same source file
throw(permission_error(modify, object, Obj))
; '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Obj, _, _, _, _)) ->
% a protocol with the same identifier was defined earlier in the same source file
throw(permission_error(modify, protocol, Obj))
; '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Obj, _, _, _, _, _)) ->
% a category with the same identifier was defined earlier in the same source file
throw(permission_error(modify, category, Obj))
; functor(Obj, '{}', 1) ->
% reserved syntax for object proxies
throw(permission_error(create, object, Obj))
; '$lgt_pp_entity_'(Type, _, _) ->
% opening object directive found while still compiling the previous entity
( Type == object ->
throw(existence_error(directive, end_object/0))
; Type == protocol ->
throw(existence_error(directive, end_protocol/0))
; % Type == category,
throw(existence_error(directive, end_category/0))
)
; '$lgt_print_message'(silent(compiling), compiling_entity(object, Obj)),
'$lgt_compile_object_relations'(Relations, Obj, Ctx),
'$lgt_compile_object_identifier'(Obj, Ctx),
'$lgt_save_parameter_variables'(Obj)
).
'$lgt_compile_logtalk_directive'(end_object, Ctx) :-
( '$lgt_pp_object_'(Obj, _, _, _, _, _, _, _, _, _, _) ->
% we're indeed compiling an object
'$lgt_pp_referenced_object_'(Obj, _, Start-_),
'$lgt_comp_ctx_lines'(Ctx, _-End),
assertz('$lgt_pp_entity_lines_'(Obj, Start-End)),
'$lgt_second_stage'(object, Obj, Ctx),
'$lgt_print_message'(silent(compiling), compiled_entity(object, Obj))
; % entity ending directive mismatch
throw(existence_error(directive, object/1))
).
% protocol opening and closing directives
'$lgt_compile_logtalk_directive'(protocol(Ptc), Ctx) :-
'$lgt_compile_logtalk_directive'(protocol_(Ptc, []), Ctx).
'$lgt_compile_logtalk_directive'(protocol(Ptc, Relation), Ctx) :-
'$lgt_compile_logtalk_directive'(protocol_(Ptc, [Relation]), Ctx).
% auxiliary predicate to compile all variants to the protocol opening directive
'$lgt_compile_logtalk_directive'(protocol_(Ptc, Relations), Ctx) :-
( var(Ptc) ->
throw(instantiation_error)
; \+ atom(Ptc) ->
throw(type_error(protocol_identifier, Ptc))
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Ptc, _, _, _, _, _, _, _, _, _, _)) ->
% an object with the same identifier was defined earlier in the same source file
throw(permission_error(modify, object, Ptc))
; '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Ptc, _, _, _, _)) ->
% a protocol with the same identifier was defined earlier in the same source file
throw(permission_error(modify, protocol, Ptc))
; '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Ptc, _, _, _, _, _)) ->
% a category with the same identifier was defined earlier in the same source file
throw(permission_error(modify, category, Ptc))
; '$lgt_pp_entity_'(Type, _, _) ->
% opening protocol directive found while still compiling the previous entity
( Type == object ->
throw(existence_error(directive, end_object/0))
; Type == protocol ->
throw(existence_error(directive, end_protocol/0))
; % Type == category,
throw(existence_error(directive, end_category/0))
)
; '$lgt_print_message'(silent(compiling), compiling_entity(protocol, Ptc)),
'$lgt_compile_protocol_identifier'(Ptc, Ctx),
'$lgt_compile_protocol_relations'(Relations, Ptc, Ctx)
).
'$lgt_compile_logtalk_directive'(end_protocol, Ctx) :-
( '$lgt_pp_protocol_'(Ptc, _, _, _, _) ->
% we're indeed compiling a protocol
'$lgt_pp_referenced_protocol_'(Ptc, _, Start-_),
'$lgt_comp_ctx_lines'(Ctx, _-End),
assertz('$lgt_pp_entity_lines_'(Ptc, Start-End)),
'$lgt_second_stage'(protocol, Ptc, Ctx),
'$lgt_print_message'(silent(compiling), compiled_entity(protocol, Ptc))
; % entity ending directive mismatch
throw(existence_error(directive, protocol/1))
).
% category opening and closing directives
'$lgt_compile_logtalk_directive'(category(Ctg), Ctx) :-
'$lgt_compile_logtalk_directive'(category_(Ctg, []), Ctx).
'$lgt_compile_logtalk_directive'(category(Ctg, Relation), Ctx) :-
'$lgt_compile_logtalk_directive'(category_(Ctg, [Relation]), Ctx).
'$lgt_compile_logtalk_directive'(category(Ctg, Relation1, Relation2), Ctx) :-
'$lgt_compile_logtalk_directive'(category_(Ctg, [Relation1, Relation2]), Ctx).
'$lgt_compile_logtalk_directive'(category(Ctg, Relation1, Relation2, Relation3), Ctx) :-
'$lgt_compile_logtalk_directive'(category_(Ctg, [Relation1, Relation2, Relation3]), Ctx).
% auxiliary predicate to compile all variants to the category opening directive
'$lgt_compile_logtalk_directive'(category_(Ctg, Relations), Ctx) :-
( var(Ctg) ->
throw(instantiation_error)
; \+ callable(Ctg) ->
throw(type_error(category_identifier, Ctg))
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Ctg, _, _, _, _, _, _, _, _, _, _)) ->
% an object with the same identifier was defined earlier in the same source file
throw(permission_error(modify, object, Ctg))
; '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Ctg, _, _, _, _)) ->
% a protocol with the same identifier was defined earlier in the same source file
throw(permission_error(modify, protocol, Ctg))
; '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Ctg, _, _, _, _, _)) ->
% a category with the same identifier was defined earlier in the same source file
throw(permission_error(modify, category, Ctg))
; '$lgt_pp_entity_'(Type, _, _) ->
% opening protocol directive found while still compiling the previous entity
( Type == object ->
throw(existence_error(directive, end_object/0))
; Type == protocol ->
throw(existence_error(directive, end_protocol/0))
; % Type == category,
throw(existence_error(directive, end_category/0))
)
; '$lgt_print_message'(silent(compiling), compiling_entity(category, Ctg)),
'$lgt_compile_category_identifier'(Ctg, Ctx),
'$lgt_compile_category_relations'(Relations, Ctg, Ctx),
'$lgt_save_parameter_variables'(Ctg)
).
'$lgt_compile_logtalk_directive'(end_category, Ctx) :-
( '$lgt_pp_category_'(Ctg, _, _, _, _, _) ->
% we're indeed compiling a category
'$lgt_pp_referenced_category_'(Ctg, _, Start-_),
'$lgt_comp_ctx_lines'(Ctx, _-End),
assertz('$lgt_pp_entity_lines_'(Ctg, Start-End)),
'$lgt_second_stage'(category, Ctg, Ctx),
'$lgt_print_message'(silent(compiling), compiled_entity(category, Ctg))
; % entity ending directive mismatch
throw(existence_error(directive, category/1))
).
% compile modules as objects
'$lgt_compile_logtalk_directive'(module(Module), Ctx) :-
% empty export list
'$lgt_compile_logtalk_directive'(module(Module, []), Ctx).
'$lgt_compile_logtalk_directive'(module(Module, Exports), Ctx) :-
'$lgt_check'(module_identifier, Module),
'$lgt_check'(list, Exports),
% remember we are compiling a module
assertz('$lgt_pp_module_'(Module)),
'$lgt_print_message'(silent(compiling), compiling_entity(module, Module)),
'$lgt_compile_object_identifier'(Module, Ctx),
% make the export list the public resources list
'$lgt_compile_logtalk_directive'(public(Exports), Ctx).
% set_logtalk_flag/2 entity directive
'$lgt_compile_logtalk_directive'(set_logtalk_flag(Flag, Value), _) :-
'$lgt_check'(read_write_flag, Flag),
'$lgt_check'(flag_value, Flag+Value),
retractall('$lgt_pp_entity_compiler_flag_'(Flag, _)),
assertz('$lgt_pp_entity_compiler_flag_'(Flag, Value)).
% declare an entity as built-in
'$lgt_compile_logtalk_directive'(built_in, Ctx) :-
( ( '$lgt_pp_dynamic_'
; '$lgt_comp_ctx_mode'(Ctx, runtime)
) ->
'$lgt_pp_entity_'(_, Entity, _),
throw(permission_error(declare, built_in, Entity))
; assertz('$lgt_pp_built_in_')
).
% create a message queue at object initialization
'$lgt_compile_logtalk_directive'(threaded, _) :-
'$lgt_pp_entity_'(Type, _, _),
( '$lgt_prolog_feature'(engines, unsupported),
'$lgt_prolog_feature'(threads, unsupported) ->
throw(resource_error(threads))
; Type == object ->
assertz('$lgt_pp_threaded_')
; Type == protocol ->
throw(domain_error(protocol_directive, threaded/0))
; % Type == category,
throw(domain_error(category_directive, threaded/0))
).
% dynamic/0 entity directive
%
% (entities are static by default but can be declared dynamic using this directive)
'$lgt_compile_logtalk_directive'((dynamic), _) :-
( '$lgt_pp_built_in_' ->
'$lgt_pp_entity_'(_, Entity, _),
throw(permission_error(declare, (dynamic), Entity))
; assertz('$lgt_pp_dynamic_')
).
% initialization/1 object directive
%
% this directive cannot be used in categories and protocols as it's not always
% possible to correctly compile initialization goals as there's no valid
% compilation context values for "sender", "this", and "self"
'$lgt_compile_logtalk_directive'(initialization(Goal), Ctx) :-
'$lgt_pp_entity_'(Type, Entity, Prefix),
( Type == object ->
% MetaVars = [] as we're compiling a local call
'$lgt_comp_ctx'(Ctx, (:- initialization(Goal)), _, Entity, Entity, Entity, Entity, Prefix, [], _, ExCtx, _, [], Lines, _),
'$lgt_execution_context'(ExCtx, Entity, Entity, Entity, Entity, [], []),
% save the source data information for use in the second compiler stage
% (where it might be required by calls to the logtalk_load_context/2
% predicate during goal expansion)
( '$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines) ->
SourceData = sd(Term, VariableNames, Singletons, File, Lines)
; SourceData = nil
),
( '$lgt_compiler_flag'(debug, on) ->
assertz('$lgt_pp_object_initialization_'(dgoal(Goal,Ctx), SourceData, Lines))
; assertz('$lgt_pp_object_initialization_'(goal(Goal,Ctx), SourceData, Lines))
)
; Type == protocol ->
throw(domain_error(protocol_directive, (initialization)/1))
; % Type == category,
throw(domain_error(category_directive, (initialization)/1))
).
% op/3 entity directive (operators are local to entities)
'$lgt_compile_logtalk_directive'(op(Priority, Specifier, Operators), Ctx) :-
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, l, File, Lines, Mode).
% uses/1 entity directive
'$lgt_compile_logtalk_directive'(uses(Aliases), _) :-
'$lgt_pp_entity_'(protocol, _, _),
throw(error(domain_error(directive, uses/1), directive(uses(Aliases)))).
'$lgt_compile_logtalk_directive'(uses(Aliases), Ctx) :-
'$lgt_compile_uses_directive'(Aliases, Aliases, Ctx).
% uses/2 predicate directive
'$lgt_compile_logtalk_directive'(uses(Obj, Resources), _) :-
'$lgt_pp_entity_'(protocol, _, _),
throw(error(domain_error(directive, uses/2), directive(uses(Obj, Resources)))).
'$lgt_compile_logtalk_directive'(uses(Obj, _), _) :-
callable(Obj),
'$lgt_pp_entity_'(object, Obj, _),
% recursive reference to the object being compiled
throw(permission_error(uses, self, Obj)).
'$lgt_compile_logtalk_directive'(uses(Obj, Resources), Ctx) :-
term_variables(Obj, [ObjVariable| ObjVariables]),
'$lgt_pp_term_source_data_'((:- uses(Obj,Resources)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
'$lgt_member_var'(Variable, [ObjVariable| ObjVariables]),
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs),
% object argument is or contains a parameter variable
!,
'$lgt_compile_uses_directive'(Resources, Resources, Obj, true, Ctx).
'$lgt_compile_logtalk_directive'(uses(Obj, Resources), Ctx) :-
'$lgt_comp_ctx_entity'(Ctx, Entity),
term_variables(Entity, [EntityVariable| EntityVariables]),
'$lgt_pp_term_source_data_'((:- uses(Obj,Resources)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
'$lgt_member_var'(Variable, [EntityVariable| EntityVariables]),
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs),
% directive uses an entity parameter variable
!,
'$lgt_compile_uses_directive'(Resources, Resources, Obj, true, Ctx).
'$lgt_compile_logtalk_directive'(uses(Obj, Resources), Ctx) :-
'$lgt_check'(object_identifier, Obj),
'$lgt_add_referenced_object'(Obj, Ctx),
'$lgt_compile_uses_directive'(Resources, Resources, Obj, false, Ctx).
% use_module/1 entity directive
'$lgt_compile_logtalk_directive'(use_module(FileSpec), _) :-
'$lgt_pp_module_'(_),
% compiling a module as an object but Logtalk only supports use_module/2 directives
throw(error(domain_error(directive, use_module/1), directive(use_module(FileSpec)))).
'$lgt_compile_logtalk_directive'(use_module(Aliases), _) :-
'$lgt_prolog_feature'(modules, unsupported),
throw(error(domain_error(directive, use_module/1), directive(use_module(Aliases)))).
'$lgt_compile_logtalk_directive'(use_module(Aliases), _) :-
'$lgt_pp_entity_'(protocol, _, _),
throw(error(domain_error(directive, use_module/1), directive(use_module(Aliases)))).
'$lgt_compile_logtalk_directive'(use_module(Aliases), Ctx) :-
'$lgt_compile_use_module_directive'(Aliases, Aliases, Ctx).
% use_module/2 predicate directive
%
% the first argument must be a module identifier; when a file specification
% is used, as it's usual in Prolog, it must be expanded at the adapter file
% level into a module identifier
'$lgt_compile_logtalk_directive'(use_module(Module, Imports), _) :-
'$lgt_pp_entity_'(protocol, _, _),
throw(error(domain_error(directive, use_module/2), directive(use_module(Module, Imports)))).
'$lgt_compile_logtalk_directive'(use_module(Module, _), _) :-
atom(Module),
'$lgt_pp_module_'(Module),
% recursive reference to the module being compiled as an object
throw(permission_error(use_module, self, Module)).
'$lgt_compile_logtalk_directive'(use_module(Module, Imports), Ctx) :-
var(Module),
'$lgt_pp_term_source_data_'((:- use_module(Module,Imports)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
Module == Variable,
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs),
% module argument is a parameter variable
!,
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_uses_directive'(Imports, Imports, Module, true, Ctx)
; '$lgt_prolog_feature'(modules, unsupported) ->
% use_module/2 directives in objects or categories require a backend supporting modules
throw(error(domain_error(directive, use_module/2), directive(use_module(Module, Imports))))
; % we're calling module predicates from within an object or a category
'$lgt_compile_use_module_directive'(Imports, Imports, Module, true, Ctx)
).
'$lgt_compile_logtalk_directive'(use_module(Module, Imports), Ctx) :-
'$lgt_check'(module_identifier, Module),
'$lgt_comp_ctx_entity'(Ctx, Entity),
term_variables(Entity, [EntityVariable| EntityVariables]),
'$lgt_pp_term_source_data_'((:- use_module(Module,Imports)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
'$lgt_member_var'(Variable, [EntityVariable| EntityVariables]),
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs),
% directive uses an entity parameter variable
!,
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_uses_directive'(Imports, Imports, Module, true, Ctx)
; '$lgt_prolog_feature'(modules, unsupported) ->
% use_module/2 directives in objects or categories require a backend supporting modules
throw(error(domain_error(directive, use_module/2), directive(use_module(Module, Imports))))
; % we're calling module predicates from within an object or a category
'$lgt_compile_use_module_directive'(Imports, Imports, Module, true, Ctx)
).
'$lgt_compile_logtalk_directive'(use_module(Module, Imports), Ctx) :-
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_uses_directive'(Imports, Imports, Module, false, Ctx)
; '$lgt_prolog_feature'(modules, unsupported) ->
% use_module/2 directives in objects or categories require a backend supporting modules
throw(error(domain_error(directive, use_module/2), directive(use_module(Module, Imports))))
; % we're calling module predicates from within an object or a category
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_compile_use_module_directive'(Imports, Imports, Module, false, Ctx)
).
% reexport/2 module directive
%
% the first argument must be a module identifier; when a file specification
% is used, as it's usual in Prolog, it must be expanded at the adapter file
% level into a module identifier
'$lgt_compile_logtalk_directive'(reexport(Module, Exports), Ctx) :-
% we must be compiling a module as an object
( '$lgt_pp_module_'(_) ->
% assume referenced modules are also compiled as objects
'$lgt_check'(module_identifier, Module),
'$lgt_check'(list, Exports),
'$lgt_compile_reexport_directive'(Exports, Module, Ctx)
; throw(error(domain_error(directive, (reexport)/2), directive(reexport(Module, Exports))))
).
% info/1 entity directive
'$lgt_compile_logtalk_directive'(info(Pairs), Ctx) :-
'$lgt_compile_entity_info_directive'(Pairs, TPairs),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_entity_info_'(TPairs, File, Lines)),
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_pp_entity_'(Type, Entity, _) ->
( '$lgt_member'(date is Year/Month/Day, Pairs) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_date_format(File, Lines, Type, Entity, Year/Month/Day, Year-Month-Day)
)
; true
),
( '$lgt_member'(version is Version, Pairs),
Version \= ':'(_, ':'(_, _)) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_version_format(File, Lines, Type, Entity, Version)
)
; true
)
; true
).
% info/2 predicate directive
'$lgt_compile_logtalk_directive'(info(Pred, Pairs), Ctx) :-
'$lgt_source_file_context'(Ctx, File, Lines),
( '$lgt_valid_predicate_indicator'(Pred, Functor, Arity) ->
'$lgt_compile_predicate_info_directive'(Pairs, Functor, Arity, TPairs),
assertz('$lgt_pp_predicate_info_'(Functor/Arity, TPairs, File, Lines))
; '$lgt_valid_non_terminal_indicator'(Pred, Functor, Arity, ExtArity) ->
'$lgt_compile_predicate_info_directive'(Pairs, Functor, Arity, TPairs),
assertz('$lgt_pp_predicate_info_'(Functor/ExtArity, TPairs, File, Lines))
; var(Pred) ->
throw(instantiation_error)
; throw(type_error(predicate_indicator, Pred))
).
% synchronized/1 predicate directive
'$lgt_compile_logtalk_directive'(synchronized(Resources), Ctx) :-
'$lgt_flatten_to_list'(Resources, ResourcesFlatted),
'$lgt_compile_synchronized_directive'(ResourcesFlatted, Ctx).
% scope directives
'$lgt_compile_logtalk_directive'(public(Resources), Ctx) :-
'$lgt_flatten_to_list'(Resources, ResourcesFlatted),
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_compile_scope_directive'(ResourcesFlatted, (public), File, Lines, Ctx).
'$lgt_compile_logtalk_directive'(protected(Resources), Ctx) :-
'$lgt_flatten_to_list'(Resources, ResourcesFlatted),
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_compile_scope_directive'(ResourcesFlatted, protected, File, Lines, Ctx).
'$lgt_compile_logtalk_directive'(private(Resources), Ctx) :-
'$lgt_flatten_to_list'(Resources, ResourcesFlatted),
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_compile_scope_directive'(ResourcesFlatted, (private), File, Lines, Ctx).
% export/1 module directive
%
% module exported directives are compiled as object public directives
'$lgt_compile_logtalk_directive'(export(Exports), Ctx) :-
% we must be compiling a module as an object
( '$lgt_pp_module_'(_) ->
'$lgt_compile_logtalk_directive'(public(Exports), Ctx)
; throw(error(domain_error(directive, (export)/1), directive(export(Exports))))
).
% dynamic/1 and discontiguous/1 predicate directives
'$lgt_compile_logtalk_directive'(dynamic(Resources), Ctx) :-
'$lgt_flatten_to_list'(Resources, ResourcesFlatted),
'$lgt_compile_dynamic_directive'(ResourcesFlatted, Ctx).
'$lgt_compile_logtalk_directive'(discontiguous(Resources), Ctx) :-
'$lgt_flatten_to_list'(Resources, ResourcesFlatted),
'$lgt_compile_discontiguous_directive'(ResourcesFlatted, Ctx).
% meta_predicate/2 and meta_non_terminal/1 predicate directives
'$lgt_compile_logtalk_directive'(meta_predicate(Preds), Ctx) :-
'$lgt_flatten_to_list'(Preds, PredsFlatted),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object
'$lgt_compile_module_meta_predicate_directive'(PredsFlatted, TPredsFlatted)
; % we're compiling a Logtalk entity
TPredsFlatted = PredsFlatted
),
'$lgt_compile_meta_predicate_directive'(TPredsFlatted, Ctx).
'$lgt_compile_logtalk_directive'(meta_non_terminal(Preds), Ctx) :-
'$lgt_flatten_to_list'(Preds, PredsFlatted),
'$lgt_compile_meta_non_terminal_directive'(PredsFlatted, Ctx).
% mode/2 predicate directive
'$lgt_compile_logtalk_directive'(mode(Mode, Solutions), _) :-
(var(Mode); var(Solutions)),
throw(instantiation_error).
'$lgt_compile_logtalk_directive'(mode(Mode, _), _) :-
\+ '$lgt_valid_mode_template'(Mode),
throw(type_error(mode_term, Mode)).
'$lgt_compile_logtalk_directive'(mode(_, Solutions), _) :-
\+ '$lgt_valid_number_of_proofs'(Solutions),
throw(type_error(number_of_proofs, Solutions)).
'$lgt_compile_logtalk_directive'(mode(Mode, Solutions), Ctx) :-
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_mode_'(Mode, Solutions, File, Lines)).
% multifile/2 predicate directive
'$lgt_compile_logtalk_directive'(multifile(Preds), Ctx) :-
'$lgt_flatten_to_list'(Preds, PredsFlatted),
'$lgt_compile_multifile_directive'(PredsFlatted, Ctx).
% coinductive/1 predicate directive
'$lgt_compile_logtalk_directive'(coinductive(Preds), Ctx) :-
( '$lgt_prolog_feature'(coinduction, supported) ->
'$lgt_flatten_to_list'(Preds, PredsFlatted),
'$lgt_compile_coinductive_directive'(PredsFlatted, Ctx)
; throw(resource_error(coinduction))
).
% alias/2 entity directive
'$lgt_compile_logtalk_directive'(alias(Entity, Resources), Ctx) :-
'$lgt_check'(entity_identifier, Entity),
'$lgt_compile_alias_directive'(Resources, Resources, Entity, Ctx).
% '$lgt_compile_alias_directive'(+list, +list, @entity_identifier, +compilation_context)
%
% auxiliary predicate for compiling alias/2 directives
'$lgt_compile_alias_directive'(_, _, Entity, _) :-
'$lgt_pp_entity_'(_, Entity, _),
throw(permission_error(reference, self, Entity)).
'$lgt_compile_alias_directive'(_, _, Entity, _) :-
\+ '$lgt_pp_extended_protocol_'(Entity, _, _, _, _),
\+ '$lgt_pp_implemented_protocol_'(Entity, _, _, _, _),
\+ '$lgt_pp_extended_category_'(Entity, _, _, _, _, _),
\+ '$lgt_pp_imported_category_'(Entity, _, _, _, _, _),
\+ '$lgt_pp_extended_object_'(Entity, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_pp_instantiated_class_'(Entity, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_pp_specialized_class_'(Entity, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_pp_complemented_object_'(Entity, _, _, _, _),
throw(domain_error(ancestor, Entity)).
'$lgt_compile_alias_directive'([Resource| Resources], Argument, Entity, Ctx) :-
!,
'$lgt_check'(ground, Resource),
'$lgt_compile_alias_directive_resource'(Resource, Entity, Ctx),
'$lgt_compile_alias_directive'(Resources, Argument, Entity, Ctx).
'$lgt_compile_alias_directive'([], _, _, _) :-
!.
'$lgt_compile_alias_directive'(_, Argument, _, _) :-
throw(type_error(list, Argument)).
'$lgt_compile_alias_directive_resource'(as(Original,Alias), Entity, Ctx) :-
!,
'$lgt_compile_alias_directive_resource'(Original::Alias, Entity, Ctx).
'$lgt_compile_alias_directive_resource'(Original::Alias, Entity, Ctx) :-
!,
'$lgt_check'(predicate_or_non_terminal_indicator, Original),
'$lgt_check'(predicate_or_non_terminal_indicator, Alias),
'$lgt_compile_alias_directive_resource'(Original, Alias, Entity, Ctx).
'$lgt_compile_alias_directive_resource'(Resource, _, _) :-
throw(type_error(predicate_alias_specification, Resource)).
'$lgt_compile_alias_directive_resource'(Functor1/Arity, Functor2/Arity, Entity, Ctx) :-
!,
functor(Pred, Functor1, Arity),
Pred =.. [Functor1| Args],
Alias =.. [Functor2| Args],
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_predicate_alias_'(Entity, Pred, Alias, 0, File, Lines)).
'$lgt_compile_alias_directive_resource'(Functor1//Arity, Functor2//Arity, Entity, Ctx) :-
!,
ExtArity is Arity + 2,
functor(Pred, Functor1, ExtArity),
Pred =.. [Functor1| Args],
Alias =.. [Functor2| Args],
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_predicate_alias_'(Entity, Pred, Alias, 1, File, Lines)).
'$lgt_compile_alias_directive_resource'(Functor1//Arity1, Functor2//Arity2, _, _) :-
throw(consistency_error(same_arity, Functor1//Arity1, Functor2//Arity2)).
'$lgt_compile_alias_directive_resource'(Functor1/Arity1, Functor2/Arity2, _, _) :-
throw(consistency_error(same_arity, Functor1/Arity1, Functor2/Arity2)).
'$lgt_compile_alias_directive_resource'(_/_, Functor2//Arity2, _, _) :-
throw(type_error(predicate_indicator, Functor2//Arity2)).
'$lgt_compile_alias_directive_resource'(_//_, Functor2/Arity2, _, _) :-
throw(type_error(non_terminal_indicator, Functor2/Arity2)).
% '$lgt_compile_synchronized_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling synchronized/1 directives
'$lgt_compile_synchronized_directive'(Resources, Ctx) :-
'$lgt_new_predicate_mutex'(Mutex),
'$lgt_compile_synchronized_directive'(Resources, Mutex, Ctx).
'$lgt_new_predicate_mutex'(Mutex) :-
'$lgt_pp_entity_'(_, _, Prefix),
once(retract('$lgt_pp_predicate_mutex_counter_'(Old))),
New is Old + 1,
asserta('$lgt_pp_predicate_mutex_counter_'(New)),
number_codes(New, Codes),
atom_codes(Atom, Codes),
atom_concat(Prefix, 'pred_mutex_', Aux),
atom_concat(Aux, Atom, Mutex).
% note that the clause order ensures that instantiation errors will be caught by
% the call to the '$lgt_compile_synchronized_directive_resource'/1 predicate
'$lgt_compile_synchronized_directive'([Resource| Resources], Mutex, Ctx) :-
'$lgt_compile_synchronized_directive_resource'(Resource, Mutex, Ctx),
'$lgt_compile_synchronized_directive'(Resources, Mutex, Ctx).
'$lgt_compile_synchronized_directive'([], _, _).
'$lgt_compile_synchronized_directive_resource'(Pred, Mutex, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
functor(Head, Functor, Arity),
( '$lgt_pp_dynamic_'(Head, _, _, _) ->
% synchronized predicates must be static
throw(permission_error(modify, dynamic_predicate, Functor/Arity))
; '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _) ->
% synchronized/1 directives must precede the definitions for the declared predicates
throw(permission_error(modify, predicate_interpretation, Functor/Arity))
; '$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_synchronized_'(Head, Mutex, File, Lines))
).
'$lgt_compile_synchronized_directive_resource'(NonTerminal, Mutex, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, Arity, ExtArity),
!,
functor(Head, Functor, ExtArity),
( '$lgt_pp_dynamic_'(Head, _, _, _) ->
% synchronized non-terminals must be static
throw(permission_error(modify, dynamic_non_terminal, Functor//Arity))
; '$lgt_pp_defines_non_terminal_'(Functor, Arity, _) ->
throw(permission_error(modify, non_terminal_interpretation, Functor//Arity))
; '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _) ->
% synchronized/1 directives must precede the definitions for the declared non-terminals
throw(permission_error(modify, non_terminal_interpretation, Functor//Arity))
; '$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_synchronized_'(Head, Mutex, File, Lines))
).
'$lgt_compile_synchronized_directive_resource'(Resource, _, _) :-
ground(Resource),
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_synchronized_directive_resource'(_, _, _) :-
throw(instantiation_error).
% '$lgt_compile_scope_directive'(+list, @scope, +atom, +integer, +compilation_context)
%
% auxiliary predicate for compiling scope directives
%
% note that the clause order ensures that instantiation errors will be caught
% by the call to the '$lgt_compile_scope_directive_resource'/1 predicate
'$lgt_compile_scope_directive'([Resource| Resources], Scope, File, Lines, Ctx) :-
'$lgt_compile_scope_directive_resource'(Resource, Scope, File, Lines, Ctx),
'$lgt_compile_scope_directive'(Resources, Scope, File, Lines, Ctx).
'$lgt_compile_scope_directive'([], _, _, _, _).
% '$lgt_compile_scope_directive_resource'(@term, @scope, +integer, +compilation_context)
%
% auxiliary predicate for compiling scope directive resources
'$lgt_compile_scope_directive_resource'(op(Priority, Specifier, Operators), Scope, File, Lines, Ctx) :-
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
!,
'$lgt_check_for_duplicated_scope_directives'(op(Priority, Specifier, Operators), Scope),
'$lgt_scope'(Scope, InternalScope),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, InternalScope, File, Lines, Mode).
'$lgt_compile_scope_directive_resource'(Functor/Arity, Scope, File, StartLine-EndLine, _) :-
'$lgt_valid_predicate_indicator'(Functor/Arity, Functor, Arity),
functor(Pred, Functor, Arity),
( '$lgt_built_in_method'(Pred, _, _, _) ->
% clash with a built-in method, whose scope cannot be changed
throw(permission_error(modify, built_in_method, Functor/Arity))
; !,
'$lgt_check_for_duplicated_scope_directives'(Functor/Arity, Scope),
'$lgt_add_predicate_scope_directive'(Scope, Functor, Arity, File, StartLine-EndLine),
assertz('$lgt_pp_predicate_declaration_location_'(Functor, Arity, File, StartLine-EndLine))
).
'$lgt_compile_scope_directive_resource'(Functor//Arity, Scope, File, StartLine-EndLine, _) :-
'$lgt_valid_non_terminal_indicator'(Functor//Arity, Functor, Arity, ExtArity),
functor(Pred, Functor, ExtArity),
( '$lgt_built_in_method'(Pred, _, _, _) ->
% clash with a built-in method, whose scope cannot be changed
throw(permission_error(modify, built_in_method, Functor//Arity))
; !,
'$lgt_check_for_duplicated_scope_directives'(Functor//Arity+ExtArity, Scope),
assertz('$lgt_pp_non_terminal_'(Functor, Arity, ExtArity)),
'$lgt_add_predicate_scope_directive'(Scope, Functor, ExtArity, File, StartLine-EndLine),
assertz('$lgt_pp_predicate_declaration_location_'(Functor, ExtArity, File, StartLine-EndLine))
).
'$lgt_compile_scope_directive_resource'(Resource, _, _, _, _) :-
ground(Resource),
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_scope_directive_resource'(_, _, _, _, _) :-
throw(instantiation_error).
'$lgt_add_predicate_scope_directive'((public), Functor, Arity, File, Lines) :-
assertz('$lgt_pp_public_'(Functor, Arity, File, Lines)).
'$lgt_add_predicate_scope_directive'(protected, Functor, Arity, File, Lines) :-
assertz('$lgt_pp_protected_'(Functor, Arity, File, Lines)).
'$lgt_add_predicate_scope_directive'((private), Functor, Arity, File, Lines) :-
assertz('$lgt_pp_private_'(Functor, Arity, File, Lines)).
'$lgt_check_for_duplicated_scope_directives'(op(_, _, []), _) :-
!.
'$lgt_check_for_duplicated_scope_directives'(op(Priority, Specifier, [Operator| Operators]), Scope) :-
!,
( '$lgt_pp_entity_operator_'(Priority, Specifier, Operator, Scope, OriginalFile, OriginalLines) ->
( '$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
Directive =.. [Scope, op(Priority, Specifier, Operator)],
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, Directive, OriginalFile, OriginalLines)
)
; true
)
; % allow a local operator to also be declared in a scope directive to simplify
% compilation of included files and compilation of modules as objects
'$lgt_pp_entity_operator_'(Priority, Specifier, Operator, OriginalScope, _, _),
OriginalScope \== l ->
throw(permission_error(modify, operator_scope, op(Priority, Specifier, Operator)))
; '$lgt_check_for_duplicated_scope_directives'(op(Priority, Specifier, Operators), Scope)
).
'$lgt_check_for_duplicated_scope_directives'(op(Priority, Specifier, Operator), Scope) :-
( '$lgt_pp_entity_operator_'(Priority, Specifier, Operator, Scope, OriginalFile, OriginalLines) ->
( '$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
Directive =.. [Scope, op(Priority, Specifier, Operator)],
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, Directive, OriginalFile, OriginalLines)
)
; true
)
; % allow a local operator to also be declared in a scope directive to simplify
% compilation of included files and compilation of modules as objects
'$lgt_pp_entity_operator_'(Priority, Specifier, Operator, OriginalScope, _, _),
OriginalScope \== l ->
throw(permission_error(modify, operator_scope, op(Priority, Specifier, Operator)))
; true
).
'$lgt_check_for_duplicated_scope_directives'(Functor/Arity, Scope) :-
( ( Scope == (public), '$lgt_pp_public_'(Functor, Arity, OriginalFile, OriginalLines)
; Scope == protected, '$lgt_pp_protected_'(Functor, Arity, OriginalFile, OriginalLines)
; Scope == (private), '$lgt_pp_private_'(Functor, Arity, OriginalFile, OriginalLines)
) ->
( '$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
Directive =.. [Scope, Functor/Arity],
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, Directive, OriginalFile, OriginalLines)
)
; true
)
; ( '$lgt_pp_public_'(Functor, Arity, _, _)
; '$lgt_pp_protected_'(Functor, Arity, _, _)
; '$lgt_pp_private_'(Functor, Arity, _, _)
) ->
throw(permission_error(modify, predicate_scope, Functor/Arity))
; true
).
'$lgt_check_for_duplicated_scope_directives'(Functor//Arity+ExtArity, Scope) :-
( ( Scope == (public), '$lgt_pp_public_'(Functor, ExtArity, OriginalFile, OriginalLines)
; Scope == protected, '$lgt_pp_protected_'(Functor, ExtArity, OriginalFile, OriginalLines)
; Scope == (private), '$lgt_pp_private_'(Functor, ExtArity, OriginalFile, OriginalLines)
) ->
( '$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
Directive =.. [Scope, Functor//Arity],
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, Directive, OriginalFile, OriginalLines)
)
; true
)
; ( '$lgt_pp_public_'(Functor, ExtArity, _, _)
; '$lgt_pp_protected_'(Functor, ExtArity, _, _)
; '$lgt_pp_private_'(Functor, ExtArity, _, _)
) ->
throw(permission_error(modify, non_terminal_scope, Functor//Arity))
; true
).
% '$lgt_compile_dynamic_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling dynamic/1 directives
%
% note that the clause order ensures that instantiation errors will be caught
% by the call to the '$lgt_compile_dynamic_directive_resource'/1 predicate
'$lgt_compile_dynamic_directive'([Resource| Resources], Ctx) :-
'$lgt_compile_dynamic_directive_resource'(Resource, Ctx),
'$lgt_compile_dynamic_directive'(Resources, Ctx).
'$lgt_compile_dynamic_directive'([], _).
'$lgt_compile_dynamic_directive_resource'(Entity::Resource, Ctx) :-
'$lgt_check'(entity_identifier, Entity),
nonvar(Resource),
'$lgt_pp_entity_'(_, Entity0, _),
'$lgt_variant'(Entity, Entity0),
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(general, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(general),
redundant_entity_qualifier_in_predicate_directive(File, Lines, Type, Entity, Entity::Resource)
)
; true
),
'$lgt_compile_dynamic_directive_resource'(Resource, Ctx).
'$lgt_compile_dynamic_directive_resource'(Entity::Pred, _) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
( Entity == user ->
'$lgt_check_for_duplicated_directive'(dynamic(Functor/Arity), dynamic(Entity::Pred)),
assertz('$lgt_pp_directive_'(dynamic(Functor/Arity)))
; '$lgt_check'(entity_identifier, Entity),
functor(Template, Functor, Arity),
'$lgt_check_primary_dynamic_declaration'(Entity, Template) ->
'$lgt_entity_to_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
'$lgt_check_for_duplicated_directive'(dynamic(TFunctor/TArity), dynamic(Entity::Pred)),
assertz('$lgt_pp_directive_'(dynamic(TFunctor/TArity)))
; throw(permission_error(modify, predicate_declaration, Entity::Pred))
).
'$lgt_compile_dynamic_directive_resource'(Entity::NonTerminal, _) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
( Entity == user ->
'$lgt_check_for_duplicated_directive'(dynamic(Functor/ExtArity), dynamic(Entity::NonTerminal)),
assertz('$lgt_pp_directive_'(dynamic(Functor/ExtArity)))
; '$lgt_check'(entity_identifier, Entity),
functor(Template, Functor, ExtArity),
'$lgt_check_primary_dynamic_declaration'(Entity, Template) ->
'$lgt_entity_to_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/ExtArity, TFunctor/TArity),
'$lgt_check_for_duplicated_directive'(dynamic(TFunctor/TArity), dynamic(Entity::NonTerminal)),
assertz('$lgt_pp_directive_'(dynamic(TFunctor/TArity)))
; throw(permission_error(modify, non_terminal_declaration, Entity::NonTerminal))
).
'$lgt_compile_dynamic_directive_resource'(':'(Module, Pred), _) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
( Module == user ->
'$lgt_check_for_duplicated_directive'(dynamic(Functor/Arity), dynamic(':'(Module, Pred))),
assertz('$lgt_pp_directive_'(dynamic(Functor/Arity)))
; '$lgt_check'(module_identifier, Module),
'$lgt_check_for_duplicated_directive'(dynamic(':'(Module, Functor/Arity)), dynamic(':'(Module, Pred))),
assertz('$lgt_pp_directive_'(dynamic(':'(Module, Functor/Arity))))
).
'$lgt_compile_dynamic_directive_resource'(':'(Module, NonTerminal), _) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
( Module == user ->
'$lgt_check_for_duplicated_directive'(dynamic(Functor/ExtArity), dynamic(':'(Module, NonTerminal))),
assertz('$lgt_pp_directive_'(dynamic(Functor/ExtArity)))
; '$lgt_check'(module_identifier, Module),
'$lgt_check_for_duplicated_directive'(dynamic(':'(Module, Functor/ExtArity)), dynamic(':'(Module, NonTerminal))),
assertz('$lgt_pp_directive_'(dynamic(':'(Module, Functor/ExtArity))))
).
'$lgt_compile_dynamic_directive_resource'(Pred, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
functor(Head, Functor, Arity),
'$lgt_check_predicate_name_conflict'((dynamic), Head, Functor/Arity),
( '$lgt_pp_entity_'(category, _, _),
( '$lgt_pp_multifile_'(Head, _, _, _) ->
% categories cannot contain predicates that are both multifile and dynamic
throw(permission_error(declare, (dynamic), Functor/Arity))
; '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _) ->
% predicate definition occurs before the directive
throw(permission_error(declare, (dynamic), Functor/Arity))
)
; '$lgt_pp_synchronized_'(Head, _, _, _) ->
% synchronized predicates must be static
throw(permission_error(modify, synchronized_predicate, Functor/Arity))
; '$lgt_check_for_duplicated_dynamic_directive'(Head, Pred),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_dynamic_'(Head, Functor/Arity, File, Lines))
).
'$lgt_compile_dynamic_directive_resource'(NonTerminal, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, Arity, ExtArity),
!,
functor(Head, Functor, ExtArity),
'$lgt_check_predicate_name_conflict'((dynamic), Head, Functor//Arity),
( '$lgt_pp_entity_'(category, _, _),
( '$lgt_pp_multifile_'(Head, _, _, _) ->
% categories cannot contain non-terminals that are both multifile and dynamic
throw(permission_error(declare, (dynamic), Functor//Arity))
; '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _) ->
% predicate definition occurs before the directive
throw(permission_error(declare, (dynamic), Functor//Arity))
)
; '$lgt_pp_synchronized_'(Head, _, _, _) ->
% synchronized non-terminals must be static
throw(permission_error(modify, synchronized_non_terminal, Functor//Arity))
; '$lgt_check_for_duplicated_dynamic_directive'(Head, NonTerminal),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_dynamic_'(Head, Functor//Arity, File, Lines))
).
'$lgt_compile_dynamic_directive_resource'(Resource, _) :-
ground(Resource),
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_dynamic_directive_resource'(_, _) :-
throw(instantiation_error).
'$lgt_check_for_duplicated_dynamic_directive'(Head, PI) :-
( '$lgt_pp_dynamic_'(Head, _, OriginalFile, OriginalLines),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, dynamic(PI), OriginalFile, OriginalLines)
)
; true
).
'$lgt_check_primary_dynamic_declaration'(Entity, Pred) :-
% the object or category holding the primary declaration must be loaded
( '$lgt_current_object_'(Entity, _, Dcl, _, _, _, _, _, _, _, _)
; '$lgt_current_category_'(Entity, _, Dcl, _, _, _)
), !,
% the predicate must be declared (i.e. have a scope directive) and dynamic
( call(Dcl, Pred, Scope, _, Flags) ->
functor(Scope, p, _),
Flags /\ 2 =:= 2
; fail
).
% '$lgt_compile_discontiguous_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling discontiguous/1 directives
%
% note that the clause order ensures that instantiation errors will be caught by
% the call to the '$lgt_compile_discontiguous_directive_resource'/1 predicate
'$lgt_compile_discontiguous_directive'([Resource| Resources], Ctx) :-
'$lgt_compile_discontiguous_directive_resource'(Resource, Ctx),
'$lgt_compile_discontiguous_directive'(Resources, Ctx).
'$lgt_compile_discontiguous_directive'([], _).
'$lgt_compile_discontiguous_directive_resource'(Entity::Resource, Ctx) :-
'$lgt_check'(entity_identifier, Entity),
nonvar(Resource),
'$lgt_pp_entity_'(_, Entity0, _),
'$lgt_variant'(Entity, Entity0),
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(general, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(general),
redundant_entity_qualifier_in_predicate_directive(File, Lines, Type, Entity, Entity::Resource)
)
; true
),
'$lgt_compile_discontiguous_directive_resource'(Resource, Ctx).
'$lgt_compile_discontiguous_directive_resource'(Entity::Pred, _) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
( Entity == user ->
'$lgt_check_for_duplicated_directive'(discontiguous(Functor/Arity), discontiguous(Entity::Pred)),
assertz('$lgt_pp_directive_'(discontiguous(Functor/Arity)))
; '$lgt_check'(entity_identifier, Entity),
'$lgt_entity_to_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
'$lgt_check_for_duplicated_directive'(discontiguous(TFunctor/TArity), discontiguous(Entity::Pred)),
assertz('$lgt_pp_directive_'(discontiguous(TFunctor/TArity)))
).
'$lgt_compile_discontiguous_directive_resource'(Entity::NonTerminal, _) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
( Entity == user ->
'$lgt_check_for_duplicated_directive'(discontiguous(Functor/ExtArity), discontiguous(Entity::NonTerminal)),
assertz('$lgt_pp_directive_'(discontiguous(Functor/ExtArity)))
; '$lgt_check'(entity_identifier, Entity),
'$lgt_entity_to_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/ExtArity, TFunctor/TArity),
'$lgt_check_for_duplicated_directive'(discontiguous(TFunctor/TArity), discontiguous(Entity::NonTerminal)),
assertz('$lgt_pp_directive_'(discontiguous(TFunctor/TArity)))
).
'$lgt_compile_discontiguous_directive_resource'(':'(Module, Pred), _) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
( Module == user ->
'$lgt_check_for_duplicated_directive'(discontiguous(Functor/Arity), discontiguous(':'(Module, Pred))),
assertz('$lgt_pp_directive_'(discontiguous(Functor/Arity)))
; '$lgt_check'(module_identifier, Module),
'$lgt_check_for_duplicated_directive'(discontiguous(':'(Module, Functor/Arity)), discontiguous(':'(Module, Pred))),
assertz('$lgt_pp_directive_'(discontiguous(':'(Module, Functor/Arity))))
).
'$lgt_compile_discontiguous_directive_resource'(':'(Module, NonTerminal), _) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
( Module == user ->
'$lgt_check_for_duplicated_directive'(discontiguous(Functor/ExtArity), discontiguous(':'(Module, NonTerminal))),
assertz('$lgt_pp_directive_'(discontiguous(Functor/ExtArity)))
; '$lgt_check'(module_identifier, Module),
'$lgt_check_for_duplicated_directive'(discontiguous(':'(Module, Functor/ExtArity)), discontiguous(':'(Module, NonTerminal))),
assertz('$lgt_pp_directive_'(discontiguous(':'(Module, Functor/ExtArity))))
).
'$lgt_compile_discontiguous_directive_resource'(Pred, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
functor(Head, Functor, Arity),
'$lgt_check_for_duplicated_discontiguous_directive'(Head, Pred),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_discontiguous_'(Head, File, Lines)).
'$lgt_compile_discontiguous_directive_resource'(NonTerminal, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
functor(Head, Functor, ExtArity),
'$lgt_check_for_duplicated_discontiguous_directive'(Head, NonTerminal),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_discontiguous_'(Head, File, Lines)).
'$lgt_compile_discontiguous_directive_resource'(Resource, _) :-
ground(Resource),
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_discontiguous_directive_resource'(_, _) :-
throw(instantiation_error).
'$lgt_check_for_duplicated_discontiguous_directive'(Head, PI) :-
( '$lgt_pp_discontiguous_'(Head, OriginalFile, OriginalLines),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, discontiguous(PI), OriginalFile, OriginalLines)
)
; true
).
% '$lgt_compile_meta_predicate_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling meta_predicate/1 directives
%
% note that the clause order ensures that instantiation errors will be caught by
% the call to the '$lgt_compile_meta_predicate_directive_resource'/1 predicate
'$lgt_compile_meta_predicate_directive'([Meta| Metas], Ctx) :-
'$lgt_compile_meta_predicate_directive_resource'(Meta, Ctx),
'$lgt_compile_meta_predicate_directive'(Metas, Ctx).
'$lgt_compile_meta_predicate_directive'([], _).
'$lgt_compile_meta_predicate_directive_resource'(Entity::Meta, Ctx) :-
'$lgt_valid_meta_predicate_template'(Meta),
!,
'$lgt_check'(entity_identifier, Entity),
'$lgt_term_template'(Meta, Template),
'$lgt_check_for_duplicated_meta_predicate_directive'(Entity::Template, Entity::Meta),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_meta_predicate_'(Entity::Template, Entity::Meta, File, Lines)).
'$lgt_compile_meta_predicate_directive_resource'(':'(Module, Meta), Ctx) :-
'$lgt_valid_meta_predicate_template'(Meta),
!,
'$lgt_check'(module_identifier, Module),
'$lgt_term_template'(Meta, Template),
'$lgt_check_for_duplicated_meta_predicate_directive'(':'(Module,Template), ':'(Module,Meta)),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_meta_predicate_'(':'(Module,Template), ':'(Module,Meta), File, Lines)).
'$lgt_compile_meta_predicate_directive_resource'(Meta, Ctx) :-
'$lgt_valid_meta_predicate_template'(Meta),
!,
'$lgt_term_template'(Meta, Template),
'$lgt_check_for_duplicated_meta_predicate_directive'(Template, Meta),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_meta_predicate_'(Template, Meta, File, Lines)).
'$lgt_compile_meta_predicate_directive_resource'(Meta, _) :-
ground(Meta),
throw(type_error(meta_predicate_template, Meta)).
'$lgt_compile_meta_predicate_directive_resource'(_, _) :-
throw(instantiation_error).
'$lgt_check_for_duplicated_meta_predicate_directive'(Template, Meta) :-
( '$lgt_pp_meta_predicate_'(Template, Meta, OriginalFile, OriginalLines) ->
( '$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, meta_predicate(Meta), OriginalFile, OriginalLines)
)
; true
)
; '$lgt_pp_meta_predicate_'(Template, _, _, _) ->
throw(permission_error(modify, meta_predicate_template, Meta))
; true
).
% '$lgt_compile_meta_non_terminal_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling meta_non_terminal/1 directives
%
% note that the clause order ensures that instantiation errors will be caught by
% the call to the '$lgt_compile_meta_non_terminal_directive_resource'/1 predicate
'$lgt_compile_meta_non_terminal_directive'([Meta| Metas], Ctx) :-
'$lgt_compile_meta_non_terminal_directive_resource'(Meta, Ctx),
'$lgt_compile_meta_non_terminal_directive'(Metas, Ctx).
'$lgt_compile_meta_non_terminal_directive'([], _).
'$lgt_compile_meta_non_terminal_directive_resource'(Entity::Meta, Ctx) :-
'$lgt_valid_meta_predicate_template'(Meta),
!,
'$lgt_check'(entity_identifier, Entity),
'$lgt_extend_meta_non_terminal_template'(Meta, ExtendedMeta),
'$lgt_term_template'(ExtendedMeta, Template),
'$lgt_check_for_duplicated_meta_non_terminal_directive'(Entity::Template, Entity::ExtendedMeta, Entity::Meta),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_meta_predicate_'(Entity::Template, Entity::ExtendedMeta, File, Lines)).
'$lgt_compile_meta_non_terminal_directive_resource'(':'(Module, Meta), Ctx) :-
'$lgt_valid_meta_predicate_template'(Meta),
!,
'$lgt_check'(module_identifier, Module),
'$lgt_extend_meta_non_terminal_template'(Meta, ExtendedMeta),
'$lgt_term_template'(ExtendedMeta, Template),
'$lgt_check_for_duplicated_meta_non_terminal_directive'(':'(Module, Template), ':'(Module, ExtendedMeta), ':'(Module, Meta)),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_meta_predicate_'(':'(Module, Template), ':'(Module, ExtendedMeta), File, Lines)).
'$lgt_compile_meta_non_terminal_directive_resource'(Meta, Ctx) :-
'$lgt_valid_meta_predicate_template'(Meta),
!,
'$lgt_extend_meta_non_terminal_template'(Meta, ExtendedMeta),
'$lgt_term_template'(ExtendedMeta, Template),
'$lgt_check_for_duplicated_meta_non_terminal_directive'(Template, ExtendedMeta, Meta),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_meta_predicate_'(Template, ExtendedMeta, File, Lines)).
'$lgt_compile_meta_non_terminal_directive_resource'(Meta, _) :-
ground(Meta),
throw(type_error(meta_non_terminal_template, Meta)).
'$lgt_compile_meta_non_terminal_directive_resource'(_, _) :-
throw(instantiation_error).
'$lgt_extend_meta_non_terminal_template'(Meta, ExtendedMeta) :-
Meta =.. [Functor| Args],
'$lgt_compile_meta_non_terminal_directive_args'(Args, ExtendedArgs),
ExtendedMeta =.. [Functor| ExtendedArgs].
'$lgt_compile_meta_non_terminal_directive_args'([], [*, *]).
'$lgt_compile_meta_non_terminal_directive_args'([Arg| Args], [ExtendedArg| ExtendedArgs]) :-
( integer(Arg) ->
ExtendedArg is Arg + 2
; ExtendedArg = Arg
),
'$lgt_compile_meta_non_terminal_directive_args'(Args, ExtendedArgs).
'$lgt_check_for_duplicated_meta_non_terminal_directive'(Template, ExtendedMeta, Meta) :-
( '$lgt_pp_meta_predicate_'(Template, ExtendedMeta, OriginalFile, OriginalLines) ->
( '$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, meta_non_terminal(Meta), OriginalFile, OriginalLines)
)
; true
)
; '$lgt_pp_meta_predicate_'(Template, _, _, _) ->
throw(permission_error(modify, meta_non_terminal_template, Meta))
; true
).
% '$lgt_compile_multifile_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling multifile/1 directives
%
% when the multifile predicate (or non-terminal) is declared for the module
% "user", the module prefix is removed to ensure code portability when using
% backend Prolog compilers without a module system
%
% note that the clause order ensures that instantiation errors will be caught
% by the call to the '$lgt_compile_multifile_directive_resource'/1 predicate
'$lgt_compile_multifile_directive'([Resource| Resources], Ctx) :-
'$lgt_compile_multifile_directive_resource'(Resource, Ctx),
'$lgt_compile_multifile_directive'(Resources, Ctx).
'$lgt_compile_multifile_directive'([], _).
'$lgt_compile_multifile_directive_resource'(Entity::Resource, Ctx) :-
'$lgt_check'(entity_identifier, Entity),
nonvar(Resource),
'$lgt_pp_entity_'(_, Entity0, _),
'$lgt_variant'(Entity, Entity0),
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(general, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(general),
redundant_entity_qualifier_in_predicate_directive(File, Lines, Type, Entity, Entity::Resource)
)
; true
),
'$lgt_compile_multifile_directive_resource'(Resource, Ctx).
'$lgt_compile_multifile_directive_resource'(Entity::Pred, _) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
( Entity == user ->
'$lgt_check_for_duplicated_directive'(multifile(Functor/Arity), multifile(Entity::Pred)),
assertz('$lgt_pp_directive_'(multifile(Functor/Arity)))
; functor(Template, Functor, Arity),
'$lgt_check_primary_multifile_declaration'(Entity, Template) ->
'$lgt_entity_to_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
'$lgt_check_for_duplicated_directive'(multifile(TFunctor/TArity), multifile(Entity::Pred)),
assertz('$lgt_pp_directive_'(multifile(TFunctor/TArity)))
; throw(permission_error(modify, predicate_declaration, Entity::Pred))
).
'$lgt_compile_multifile_directive_resource'(Entity::NonTerminal, _) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
( Entity == user ->
'$lgt_check_for_duplicated_directive'(multifile(Functor/ExtArity), multifile(Entity::NonTerminal)),
assertz('$lgt_pp_directive_'(multifile(Functor/ExtArity)))
; functor(Template, Functor, ExtArity),
'$lgt_check_primary_multifile_declaration'(Entity, Template) ->
'$lgt_entity_to_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/ExtArity, TFunctor/TArity),
'$lgt_check_for_duplicated_directive'(multifile(TFunctor/TArity), multifile(Entity::NonTerminal)),
assertz('$lgt_pp_directive_'(multifile(TFunctor/TArity)))
; throw(permission_error(modify, non_terminal_declaration, Entity::NonTerminal))
).
'$lgt_compile_multifile_directive_resource'(':'(Module, Pred), _) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
( Module == user ->
'$lgt_check_for_duplicated_directive'(multifile(Functor/Arity), multifile(':'(Module, Pred))),
assertz('$lgt_pp_directive_'(multifile(Functor/Arity)))
; '$lgt_check'(module_identifier, Module),
'$lgt_check_for_duplicated_directive'(multifile(':'(Module, Functor/Arity)), multifile(':'(Module, Pred))),
assertz('$lgt_pp_directive_'(multifile(':'(Module, Functor/Arity))))
).
'$lgt_compile_multifile_directive_resource'(':'(Module, NonTerminal), _) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtArity),
!,
( Module == user ->
'$lgt_check_for_duplicated_directive'(multifile(Functor/ExtArity), multifile(':'(Module, NonTerminal))),
assertz('$lgt_pp_directive_'(multifile(Functor/ExtArity)))
; '$lgt_check'(module_identifier, Module),
'$lgt_check_for_duplicated_directive'(multifile(':'(Module, Functor/ExtArity)), multifile(':'(Module, NonTerminal))),
assertz('$lgt_pp_directive_'(multifile(':'(Module, Functor/ExtArity))))
).
'$lgt_compile_multifile_directive_resource'(Pred, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
functor(Head, Functor, Arity),
'$lgt_pp_entity_'(Type, Entity, Prefix),
( Entity == user ->
'$lgt_check_for_duplicated_directive'(multifile(Functor/Arity), multifile(Pred)),
assertz('$lgt_pp_directive_'(multifile(Functor/Arity)))
; Type == protocol ->
% protocols cannot contain predicate definitions
throw(permission_error(declare, (multifile), Functor/Arity))
; Type == category,
'$lgt_pp_dynamic_'(Head, _, _, _) ->
% categories cannot contain predicates that are both multifile and dynamic
throw(permission_error(declare, (multifile), Functor/Arity))
; '$lgt_check_for_duplicated_multifile_directive'(Head, Pred),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_multifile_'(Head, Functor/Arity, File, Lines)),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
assertz('$lgt_pp_directive_'(multifile(TFunctor/TArity)))
).
'$lgt_compile_multifile_directive_resource'(NonTerminal, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, Arity, ExtArity),
!,
functor(Head, Functor, ExtArity),
'$lgt_pp_entity_'(Type, Entity, Prefix),
( Entity == user ->
'$lgt_check_for_duplicated_directive'(multifile(Functor/ExtArity), multifile(NonTerminal)),
assertz('$lgt_pp_directive_'(multifile(Functor/ExtArity)))
; Type == protocol ->
% protocols cannot contain non-terminal definitions
throw(permission_error(declare, (multifile), Functor//Arity))
; Type == category,
'$lgt_pp_dynamic_'(Head, _, _, _) ->
% categories cannot contain non-terminals that are both multifile and dynamic
throw(permission_error(declare, (multifile), Functor//Arity))
; '$lgt_check_for_duplicated_multifile_directive'(Head, NonTerminal),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_multifile_'(Head, Functor//Arity, File, Lines)),
'$lgt_compile_predicate_indicator'(Prefix, Functor/ExtArity, TFunctor/TArity),
assertz('$lgt_pp_directive_'(multifile(TFunctor/TArity)))
).
'$lgt_compile_multifile_directive_resource'(Resource, _) :-
ground(Resource),
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_multifile_directive_resource'(_, _) :-
throw(instantiation_error).
'$lgt_check_primary_multifile_declaration'(Entity, Pred) :-
% the object or category holding the primary declaration must be loaded
( '$lgt_current_object_'(Entity, _, Dcl, _, _, _, _, _, _, _, _)
; '$lgt_current_category_'(Entity, _, Dcl, _, _, _)
), !,
% the predicate must be declared (i.e. have a scope directive) and multifile
( call(Dcl, Pred, Scope, _, Flags) ->
functor(Scope, p, _),
Flags /\ 16 =:= 16
; fail
).
'$lgt_check_for_duplicated_multifile_directive'(Head, PI) :-
( '$lgt_pp_multifile_'(Head, _, OriginalFile, OriginalLines),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, multifile(PI), OriginalFile, OriginalLines)
)
; true
).
% '$lgt_compile_coinductive_directive'(+list, +compilation_context)
%
% auxiliary predicate for compiling coinductive/1 directives
%
% note that the clause order ensures that instantiation errors will be caught by
% the call to the '$lgt_compile_coinductive_directive_resource'/1 predicate
'$lgt_compile_coinductive_directive'([Pred| Preds], Ctx) :-
'$lgt_compile_coinductive_directive_resource'(Pred, Ctx),
'$lgt_compile_coinductive_directive'(Preds, Ctx).
'$lgt_compile_coinductive_directive'([], _).
'$lgt_compile_coinductive_directive_resource'(Pred, Ctx) :-
'$lgt_valid_coinductive_template'(Pred, Functor, Arity, Head, TestHead, Template),
!,
( '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _) ->
% coinductive/1 directives must precede the definitions for the declared predicates
throw(permission_error(modify, predicate_interpretation, Functor/Arity))
; true
),
% construct functor for the auxiliary predicate
atom_concat(Functor, '__coinductive', CFunctor),
% construct functor for debugging calls to the auxiliary predicate
atom_concat(Functor, '__coinduction_preflight', DFunctor),
functor(DHead, DFunctor, Arity),
Head =.. [_| Args],
DHead =.. [_| Args],
'$lgt_pp_entity_'(_, Entity, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, CFunctor/Arity, TCFunctor/TCArity),
functor(TCHead, TCFunctor, TCArity),
'$lgt_unify_head_thead_arguments'(Head, TCHead, HeadExCtx),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(THead, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(Head, THead, BodyExCtx),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_coinductive_'(Head, TestHead, HeadExCtx, TCHead, BodyExCtx, THead, DHead, File, Lines)),
assertz('$lgt_pp_coinductive_head_'(Head, HeadExCtx, TCHead)),
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, Functor/Arity, coinductive(Template)))).
'$lgt_compile_coinductive_directive_resource'(Pred, _) :-
ground(Pred),
throw(type_error(predicate_indicator, Pred)).
'$lgt_compile_coinductive_directive_resource'(_, _) :-
throw(instantiation_error).
% coinductive success is achieved when the current hypothesis is already
% present in the stack of previous hypothesis
'$lgt_check_coinductive_success'(Hypothesis, [Hypothesis| _], Hypothesis).
'$lgt_check_coinductive_success'(TestHead, [_| Stack], Hypothesis) :-
'$lgt_check_coinductive_success'(TestHead, Stack, Hypothesis).
'$lgt_valid_coinductive_template'(PredicateIndicator, Functor, Arity, Head, Head, Template) :-
'$lgt_valid_predicate_indicator'(PredicateIndicator, Functor, Arity),
!,
functor(Head, Functor, Arity),
'$lgt_construct_extended_coinductive_template'(Functor, Arity, Template).
'$lgt_valid_coinductive_template'(NonTerminal, Functor, ExtendedArity, Head, Head, Template) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, _, ExtendedArity),
!,
functor(Head, Functor, ExtendedArity),
'$lgt_construct_extended_coinductive_template'(Functor, ExtendedArity, Template).
'$lgt_valid_coinductive_template'(Template, Functor, Arity, Head, TestHead, Template) :-
'$lgt_check'(callable, Template),
'$lgt_check'(ground, Template),
functor(Template, Functor, Arity),
functor(Head, Functor, Arity),
Template =.. [Functor| TemplateArgs],
Head =.. [Functor| HeadArgs],
'$lgt_map_coinductive_template_args'(TemplateArgs, HeadArgs, TestHeadArgs),
TestHead =.. [Functor| TestHeadArgs].
% when the argument of the directive is a predicate (or non-terminal) indicator,
% we construct an extended template for the predicate by making all arguments
% relevant for testing for coinductive success
'$lgt_construct_extended_coinductive_template'(Functor, Arity, Template) :-
functor(Template, Functor, Arity),
Template =.. [Functor| Args],
'$lgt_construct_extended_coinductive_template_args'(Args).
'$lgt_construct_extended_coinductive_template_args'([]).
'$lgt_construct_extended_coinductive_template_args'([(+)| Args]) :-
'$lgt_construct_extended_coinductive_template_args'(Args).
% when only some arguments are relevant for testing for coinductive success,
% we must construct a test head where non-relevant arguments are replaced by
% anonymous variables as these will always unify with any term and thus prevent
% these arguments of causing a failure when checking for coinductive success
'$lgt_map_coinductive_template_args'([], [], []).
'$lgt_map_coinductive_template_args'([(+)| TemplateArgs], [Arg| HeadArgs], [Arg| TestHeadArgs]) :-
!,
'$lgt_map_coinductive_template_args'(TemplateArgs, HeadArgs, TestHeadArgs).
'$lgt_map_coinductive_template_args'([(-)| TemplateArgs], [_| HeadArgs], [_| TestHeadArgs]) :-
'$lgt_map_coinductive_template_args'(TemplateArgs, HeadArgs, TestHeadArgs).
% '$lgt_compile_uses_directive'(Aliases, Aliases, Ctx)
%
% auxiliary predicate for compiling uses/1 directives
'$lgt_compile_uses_directive'([Alias| Aliases], Argument, Ctx) :-
!,
'$lgt_compile_uses_directive_alias'(Alias, Argument, Ctx),
'$lgt_compile_uses_directive'(Aliases, Argument, Ctx).
'$lgt_compile_uses_directive'([], _, _) :-
!.
'$lgt_compile_uses_directive'(_, Argument, _) :-
throw(type_error(list, Argument)).
'$lgt_compile_uses_directive_alias'(Obj as Alias, Argument, Ctx) :-
var(Obj),
'$lgt_pp_term_source_data_'((:- uses(Argument)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
Obj == Variable,
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs),
% object argument is a parameter variable
!,
'$lgt_check'(object_identifier, Alias),
( \+ \+ ('$lgt_pp_object_alias_'(Other, Alias, _, _, _), Obj == Other) ->
throw(permission_error(repeat, object_alias, Alias))
; \+ \+ '$lgt_pp_object_alias_'(_, Alias, _, _, _) ->
throw(permission_error(modify, object_alias, Alias))
; % use a minimal compilation-context to preserve the binding
% between the parameter variable and the object argument
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_object_alias_'(Obj, Alias, NewCtx, File, Lines))
).
'$lgt_compile_uses_directive_alias'(Obj as Alias, Argument, Ctx) :-
!,
'$lgt_check'(object_identifier, Obj),
'$lgt_check'(object_identifier, Alias),
( \+ \+ '$lgt_pp_object_alias_'(Obj, Alias, _, _, _) ->
throw(permission_error(repeat, object_alias, Alias))
; \+ \+ '$lgt_pp_object_alias_'(_, Alias, _, _, _) ->
throw(permission_error(modify, object_alias, Alias))
; \+ \+ '$lgt_pp_object_alias_'(_, Obj, _, _, _) ->
throw(permission_error(create, alias_alias, Alias))
; '$lgt_variant'(Obj, Alias) ->
throw(consistency_error(alias_different_from_original, Obj, Alias))
; '$lgt_add_referenced_object'(Obj, Ctx),
'$lgt_source_file_context'(Ctx, File, Lines),
( term_variables(Obj, Variables),
'$lgt_pp_term_source_data_'((:- uses(Argument)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
'$lgt_member_var'(Variable, Variables),
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs) ->
% at least one of the object arguments is a parameter variable;
% use a minimal compilation-context to preserve the binding
% between the parameter variable and the object argument
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_object_alias_'(Obj, Alias, NewCtx, File, Lines))
; assertz('$lgt_pp_object_alias_'(Obj, Alias, _, File, Lines))
)
).
'$lgt_compile_uses_directive_alias'(Term, _, _) :-
throw(type_error(object_alias, Term)).
% '$lgt_compile_uses_directive'(+list, +list, @object_identifier, +boolean, +compilation_context)
%
% auxiliary predicate for compiling uses/2 directives; the boolean flag is true when the
% object argument is or contains parameter variables
'$lgt_compile_uses_directive'([Resource| Resources], Argument, Obj, Flag, Ctx) :-
!,
'$lgt_check'(nonvar, Resource),
'$lgt_compile_uses_directive_resource'(Resource, Obj, Flag, Ctx),
'$lgt_compile_uses_directive'(Resources, Argument, Obj, Flag, Ctx).
'$lgt_compile_uses_directive'([], _, _, _, _) :-
!.
'$lgt_compile_uses_directive'(_, Argument, _, _, _) :-
throw(type_error(list, Argument)).
'$lgt_compile_uses_directive_resource'(op(Priority, Specifier, Operators), _, _, Ctx) :-
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
!,
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, l, File, Lines, Mode).
'$lgt_compile_uses_directive_resource'(as(Original,Alias), Obj, Flag, Ctx) :-
!,
'$lgt_compile_uses_directive_resource'(Original::Alias, Obj, Flag, Ctx).
'$lgt_compile_uses_directive_resource'(Original::Alias, Obj, Flag, Ctx) :-
'$lgt_valid_predicate_indicator'(Original, OriginalFunctor, OriginalArity),
'$lgt_valid_predicate_indicator'(Alias, AliasFunctor, AliasArity),
!,
( Original == Alias ->
throw(consistency_error(alias_different_from_original, Original, Alias))
; OriginalArity =:= AliasArity ->
'$lgt_compile_uses_directive_predicate_indicator'(OriginalFunctor, AliasFunctor, OriginalArity, Obj, Flag, Ctx)
; throw(consistency_error(same_arity, OriginalFunctor/OriginalArity, AliasFunctor/AliasArity))
).
'$lgt_compile_uses_directive_resource'(Original::Alias, Obj, Flag, Ctx) :-
'$lgt_valid_non_terminal_indicator'(Original, OriginalFunctor, OriginalArity, ExtendedArity),
'$lgt_valid_non_terminal_indicator'(Alias, AliasFunctor, AliasArity, _),
!,
( Original == Alias ->
throw(consistency_error(alias_different_from_original, Original, Alias))
; OriginalArity =:= AliasArity ->
'$lgt_compile_uses_directive_non_terminal_indicator'(OriginalFunctor, AliasFunctor, OriginalArity, ExtendedArity, Obj, Flag, Ctx)
; throw(consistency_error(same_arity, OriginalFunctor//OriginalArity, AliasFunctor//AliasArity))
).
'$lgt_compile_uses_directive_resource'(Original::Alias, Obj, Flag, Ctx) :-
callable(Original),
callable(Alias),
!,
'$lgt_compile_uses_directive_predicate_call'(Original, Alias, Obj, Flag, Ctx).
'$lgt_compile_uses_directive_resource'(Pred, Obj, Flag, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
'$lgt_compile_uses_directive_predicate_indicator'(Functor, Functor, Arity, Obj, Flag, Ctx).
'$lgt_compile_uses_directive_resource'(NonTerminal, Obj, Flag, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, Arity, ExtArity),
!,
'$lgt_compile_uses_directive_non_terminal_indicator'(Functor, Functor, Arity, ExtArity, Obj, Flag, Ctx).
'$lgt_compile_uses_directive_resource'(Resource, _, _, _) :-
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_uses_directive_predicate_indicator'(OriginalFunctor, AliasFunctor, Arity, Obj, Flag, Ctx) :-
functor(Original, OriginalFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity),
( '$lgt_pp_uses_predicate_'(Obj, Original, Alias, _, OriginalFile, OriginalLines) ->
% predicate already listed in another uses/2 directive
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_predicate_reference(File, Lines, Type, Entity, Obj::AliasFunctor/Arity, OriginalFile, OriginalLines)
)
; true
)
; '$lgt_check_predicate_name_conflict'(uses, Alias, AliasFunctor/Arity),
% unify arguments of TOriginal and TAlias
Original =.. [_| Args],
Alias =.. [_| Args],
% allow for runtime use by adding a local definition that calls the remote definition
% except when the remote is a built-in predicate in "user" with no alias being defined
% or a built-in method that would clash with the local definition
( Obj == user,
OriginalFunctor == AliasFunctor,
'$lgt_predicate_property'(Original, built_in) ->
% no need for a local definition
true
; % add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_clause'((Alias :- Obj::Original), AuxCtx)
),
% ensure that this uses/2 directive is found when looking for senders of this message
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_object_message'(Mode, Obj, Original, Alias, Alias),
( Flag == true ->
% shared parameter variables; use a minimal compilation-context to preserve
% the binding between any parameter variable and the object argument
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_uses_predicate_'(Obj, Original, Alias, NewCtx, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Obj, Original, Alias, NewCtx)))
; assertz('$lgt_pp_uses_predicate_'(Obj, Original, Alias, _, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Obj, Original, Alias, _)))
)
).
'$lgt_compile_uses_directive_non_terminal_indicator'(OriginalFunctor, AliasFunctor, Arity, ExtArity, Obj, Flag, Ctx) :-
functor(Original, OriginalFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity),
( '$lgt_pp_uses_non_terminal_'(Obj, Original, Alias, _, _, _, OriginalFile, OriginalLines) ->
% predicate already listed in another uses/2 directive
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_non_terminal_reference(File, Lines, Type, Entity, Obj::AliasFunctor//Arity, OriginalFile, OriginalLines)
)
; true
)
; functor(Pred, OriginalFunctor, ExtArity),
functor(PredAlias, AliasFunctor, ExtArity),
'$lgt_check_predicate_name_conflict'(uses, PredAlias, AliasFunctor//Arity),
% unify arguments of TOriginal and TAlias
Original =.. [_| Args],
Alias =.. [_| Args],
% allow for runtime use by adding a local definition that calls the remote definition
% except when the remote is a built-in predicate in "user" with no alias being defined
% or a built-in method that would clash with the local definition
( Obj == user,
OriginalFunctor == AliasFunctor,
'$lgt_predicate_property'(Pred, built_in) ->
% no need for a local definition
true
; % add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_grammar_rule'((Alias --> Obj::Original), AuxCtx)
),
% ensure that the this uses/2 directive is found when looking for senders of this message
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_object_message'(Mode, Obj, Pred, PredAlias, PredAlias),
( Flag == true ->
% shared parameter variables; use a minimal compilation-context to preserve
% the binding between the parameter variable and the object argument
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_uses_non_terminal_'(Obj, Original, Alias, Pred, PredAlias, NewCtx, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Obj, Pred, PredAlias, NewCtx)))
; assertz('$lgt_pp_uses_non_terminal_'(Obj, Original, Alias, Pred, PredAlias, _, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Obj, Pred, PredAlias, _)))
)
).
'$lgt_compile_uses_directive_predicate_call'(Original, Alias, Obj, Flag, Ctx) :-
functor(Alias, AliasFunctor, Arity),
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity),
( '$lgt_pp_uses_predicate_'(Obj, Original, Alias, _, OriginalFile, OriginalLines) ->
% predicate already listed in another uses/2 directive
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_predicate_reference(File, Lines, Type, Entity, Obj::AliasFunctor/Arity, OriginalFile, OriginalLines)
)
; true
)
; '$lgt_check_predicate_name_conflict'(uses, Alias, AliasFunctor/Arity),
% allow for runtime use by adding a local definition that calls the remote definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
( Obj == user ->
'$lgt_compile_clause'((Alias :- {Original}), AuxCtx)
; '$lgt_compile_clause'((Alias :- Obj::Original), AuxCtx)
),
% ensure that this uses/2 directive is found when looking for senders of this message
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_object_message'(Mode, Obj, Original, Alias, Alias),
( Flag == true ->
% shared parameter variables; use a minimal compilation-context to preserve
% the binding between any parameter variable and the object argument
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_uses_predicate_'(Obj, Original, Alias, NewCtx, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Obj, Original, Alias, NewCtx)))
; assertz('$lgt_pp_uses_predicate_'(Obj, Original, Alias, _, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Obj, Original, Alias, _)))
)
).
% '$lgt_compile_use_module_directive'(Aliases, Aliases, Ctx)
%
% auxiliary predicate for compiling use_module/1 directives
'$lgt_compile_use_module_directive'([Alias| Aliases], Argument, Ctx) :-
!,
'$lgt_compile_use_module_directive_alias'(Alias, Argument, Ctx),
'$lgt_compile_use_module_directive'(Aliases, Argument, Ctx).
'$lgt_compile_use_module_directive'([], _, _) :-
!.
'$lgt_compile_use_module_directive'(_, Argument, _) :-
throw(type_error(list, Argument)).
'$lgt_compile_use_module_directive_alias'(Module as Alias, Argument, Ctx) :-
var(Module),
'$lgt_pp_term_source_data_'((:- use_module(Argument)), VariableNames, _, _, _),
'$lgt_member'(VariableName=Variable, VariableNames),
Module == Variable,
'$lgt_pp_parameter_variables_'(ParameterVariablePairs),
'$lgt_member'(VariableName-_, ParameterVariablePairs),
% module argument is a parameter variable
!,
'$lgt_check'(module_identifier, Alias),
( \+ \+ ('$lgt_pp_module_alias_'(Other, Alias, _, _, _), Module == Other) ->
throw(permission_error(repeat, module_alias, Alias))
; \+ \+ '$lgt_pp_module_alias_'(_, Alias, _, _, _) ->
throw(permission_error(modify, module_alias, Alias))
; % use a minimal compilation-context to preserve the binding
% between the parameter variable and the module argument
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_module_alias_'(Module, Alias, NewCtx, File, Lines))
).
'$lgt_compile_use_module_directive_alias'(Module as Alias, _, Ctx) :-
!,
'$lgt_check'(module_identifier, Module),
'$lgt_check'(module_identifier, Alias),
( \+ \+ '$lgt_pp_module_alias_'(Module, Alias, _, _, _) ->
throw(permission_error(repeat, module_alias, Alias))
; \+ \+ '$lgt_pp_module_alias_'(_, Alias, _, _, _) ->
throw(permission_error(modify, module_alias, Alias))
; \+ \+ '$lgt_pp_module_alias_'(_, Module, _, _, _) ->
throw(permission_error(create, module_alias, Alias))
; Module == Alias ->
throw(consistency_error(alias_different_from_original, Module, Alias))
; '$lgt_add_referenced_module'(Module, Ctx),
'$lgt_source_file_context'(Ctx, File, Lines),
assertz('$lgt_pp_module_alias_'(Module, Alias, _, File, Lines))
).
'$lgt_compile_use_module_directive_alias'(Term, _, _) :-
throw(type_error(module_alias, Term)).
% '$lgt_compile_use_module_directive'(+list, +list, +atom, +compilation_context)
%
% auxiliary predicate for compiling use_module/2 directives in objects or categories;
% the boolean flag is true when the module argument is a parameter variable
'$lgt_compile_use_module_directive'([Resource| Resources], Argument, Module, Flag, Ctx) :-
!,
'$lgt_check'(nonvar, Resource),
'$lgt_compile_use_module_directive_resource'(Resource, Module, Flag, Ctx),
'$lgt_compile_use_module_directive'(Resources, Argument, Module, Flag, Ctx).
'$lgt_compile_use_module_directive'([], _, _, _, _) :-
!.
'$lgt_compile_use_module_directive'(_, Argument, _, _, _) :-
throw(type_error(list, Argument)).
'$lgt_compile_use_module_directive_resource'(op(Priority, Specifier, Operators), _, _, Ctx) :-
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
!,
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, l, File, Lines, Mode).
'$lgt_compile_use_module_directive_resource'(as(Original, Alias), Module, Flag, Ctx) :-
!,
'$lgt_compile_use_module_directive_resource'(':'(Original, Alias), Module, Flag, Ctx).
'$lgt_compile_use_module_directive_resource'(':'(Original, Alias), Module, Flag, Ctx) :-
'$lgt_valid_predicate_indicator'(Original, OriginalFunctor, OriginalArity),
'$lgt_valid_predicate_indicator'(Alias, AliasFunctor, AliasArity),
!,
( Original == Alias ->
throw(consistency_error(alias_different_from_original, Original, Alias))
; OriginalArity =:= AliasArity ->
'$lgt_compile_use_module_directive_predicate_indicator'(OriginalFunctor, AliasFunctor, OriginalArity, Module, Flag, Ctx)
; throw(consistency_error(same_arity, OriginalFunctor/OriginalArity, AliasFunctor/AliasArity))
).
'$lgt_compile_use_module_directive_resource'(':'(Original, Alias), Module, Flag, Ctx) :-
'$lgt_valid_non_terminal_indicator'(Original, OriginalFunctor, OriginalArity, ExtendedArity),
'$lgt_valid_non_terminal_indicator'(Alias, AliasFunctor, AliasArity, _),
!,
( Original == Alias ->
throw(consistency_error(alias_different_from_original, Original, Alias))
; OriginalArity =:= AliasArity ->
'$lgt_compile_use_module_directive_non_terminal_indicator'(OriginalFunctor, AliasFunctor, OriginalArity, ExtendedArity, Module, Flag, Ctx)
; throw(consistency_error(same_arity, OriginalFunctor//OriginalArity, AliasFunctor//AliasArity))
).
'$lgt_compile_use_module_directive_resource'(':'(Original, Alias), Module, Flag, Ctx) :-
callable(Original),
callable(Alias),
!,
'$lgt_compile_use_module_directive_predicate_call'(Original, Alias, Module, Flag, Ctx).
'$lgt_compile_use_module_directive_resource'(Pred, Module, Flag, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
'$lgt_compile_use_module_directive_predicate_indicator'(Functor, Functor, Arity, Module, Flag, Ctx).
'$lgt_compile_use_module_directive_resource'(NonTerminal, Module, Flag, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, Arity, ExtArity),
!,
'$lgt_compile_use_module_directive_non_terminal_indicator'(Functor, Functor, Arity, ExtArity, Module, Flag, Ctx).
'$lgt_compile_use_module_directive_resource'(Resource, _, _, _) :-
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_use_module_directive_predicate_indicator'(OriginalFunctor, AliasFunctor, Arity, Module, Flag, Ctx) :-
functor(Original, OriginalFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity),
( '$lgt_pp_use_module_predicate_'(Module, Original, Alias, _, OriginalFile, OriginalLines) ->
% predicate already listed in another uses/2 directive
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_predicate_reference(File, Lines, Type, Entity, ':'(Module, AliasFunctor/Arity), OriginalFile, OriginalLines)
)
; true
)
; '$lgt_check_predicate_name_conflict'(use_module, Alias, AliasFunctor/Arity),
% unify arguments of TOriginal and TAlias
Original =.. [_| Args],
Alias =.. [_| Args],
% allow for runtime use by adding a local definition that calls the remote definition
% except when the remote is a built-in predicate in "user" with no alias being defined
% or a built-in method that would clash with the local definition
( Module == user,
OriginalFunctor == AliasFunctor,
'$lgt_predicate_property'(Original, built_in) ->
% no need for a local definition
true
; % add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_clause'((Alias :- ':'(Module,Original)), AuxCtx)
),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
% ensure that this use_module/2 directive is found when looking for callers of this module predicate
'$lgt_add_referenced_module_predicate'(Mode, Module, Original, Alias, Alias),
( Flag == true ->
% parameter variable; use a minimal compilation-context to preserve
% the binding between the parameter variable and the module argument
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_use_module_predicate_'(Module, Original, Alias, NewCtx, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_use_module_predicate_'(Entity, Module, Original, Alias, NewCtx)))
; assertz('$lgt_pp_use_module_predicate_'(Module, Original, Alias, _, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_use_module_predicate_'(Entity, Module, Original, Alias, _)))
)
).
'$lgt_compile_use_module_directive_non_terminal_indicator'(OriginalFunctor, AliasFunctor, Arity, ExtArity, Module, Flag, Ctx) :-
functor(Original, OriginalFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity),
( '$lgt_pp_use_module_non_terminal_'(Module, Original, Alias, _, _, _, OriginalFile, OriginalLines) ->
% predicate already listed in another uses/2 directive
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_non_terminal_reference(File, Lines, Type, Entity, ':'(Module, AliasFunctor//Arity), OriginalFile, OriginalLines)
)
; true
)
; functor(Pred, AliasFunctor, ExtArity),
functor(PredAlias, AliasFunctor, ExtArity),
'$lgt_check_predicate_name_conflict'(use_module, PredAlias, AliasFunctor//Arity),
% unify arguments of TOriginal and TAlias
Original =.. [_| Args],
Alias =.. [_| Args],
% allow for runtime use by adding a local definition that calls the remote definition
% except when the remote is a built-in predicate in "user" with no alias being defined
% or a built-in method that would clash with the local definition
( Module == user,
OriginalFunctor == AliasFunctor,
'$lgt_predicate_property'(Pred, built_in) ->
% no need for a local definition
true
; % add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_grammar_rule'((Alias --> ':'(Module,Original)), AuxCtx)
),
% ensure that the this use_module/2 directive is found when looking for callers of this module non-terminal
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_module_predicate'(Mode, Module, Pred, PredAlias, PredAlias),
( Flag == true ->
% parameter variable; use a minimal compilation-context to preserve
% the binding between the parameter variable and the object argument
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_use_module_non_terminal_'(Module, Original, Alias, Pred, PredAlias, NewCtx, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Module, Pred, PredAlias, NewCtx)))
; assertz('$lgt_pp_use_module_non_terminal_'(Module, Original, Alias, Pred, PredAlias, _, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_uses_predicate_'(Entity, Module, Pred, PredAlias, _)))
)
).
'$lgt_compile_use_module_directive_predicate_call'(Original, Alias, Module, Flag, Ctx) :-
functor(Alias, AliasFunctor, Arity),
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity),
( '$lgt_pp_use_module_predicate_'(Module, Original, Alias, _, OriginalFile, OriginalLines) ->
% predicate already listed in another uses/2 directive
( '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_predicate_reference(File, Lines, Type, Entity, ':'(Module, AliasFunctor/Arity), OriginalFile, OriginalLines)
)
; true
)
; '$lgt_check_predicate_name_conflict'(use_module, Alias, AliasFunctor/Arity),
% allow for runtime use by adding a local definition that calls the remote definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
( Module == user ->
'$lgt_compile_clause'((Alias :- {Original}), AuxCtx)
; '$lgt_compile_clause'((Alias :- ':'(Module,Original)), AuxCtx)
),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
% ensure that this use_module/2 directive is found when looking for callers of this module predicate
'$lgt_add_referenced_module_predicate'(Mode, Module, Original, Alias, Alias),
( Flag == true ->
% parameter variable; use a minimal compilation-context to preserve
% the binding between the parameter variable and the module argument
'$lgt_comp_ctx_exec_ctx'(NewCtx, ExCtx),
assertz('$lgt_pp_use_module_predicate_'(Module, Original, Alias, NewCtx, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_use_module_predicate_'(Entity, Module, Original, Alias, NewCtx)))
; assertz('$lgt_pp_use_module_predicate_'(Module, Original, Alias, _, File, Lines)),
assertz('$lgt_pp_runtime_clause_'('$lgt_use_module_predicate_'(Entity, Module, Original, Alias, _)))
)
).
% auxiliary predicate for checking predicate name conflicts between
% predicates listed in uses/2, use_module/2, and dynamic/1 directives
'$lgt_check_predicate_name_conflict'(Directive, Alias, Culprit) :-
( '$lgt_built_in_method'(Alias, _, _, _) ->
% clash with a built-in method, which cannot be redefined
throw(permission_error(modify, built_in_method, Culprit))
; '$lgt_pp_uses_predicate_'(Obj, _, Alias, _, _, _) ->
% clash with an earlier uses/2 directive predicate
throw(permission_error(modify, uses_object_predicate, Obj::Culprit))
; '$lgt_pp_uses_non_terminal_'(Obj, _, _, _, Alias, _, _, _) ->
% clash with an earlier uses/2 directive non-terminal
throw(permission_error(modify, uses_object_non_terminal, Obj::Culprit))
; '$lgt_pp_use_module_predicate_'(Module, _, Alias, _, _, _) ->
% clash with an earlier use_module/2 directive predicate
throw(permission_error(modify, uses_module_predicate, ':'(Module,Culprit)))
; '$lgt_pp_use_module_non_terminal_'(Module, _, _, _, Alias, _, _, _) ->
% clash with an earlier use_module/2 directive non-terminal
throw(permission_error(modify, uses_module_non_terminal, ':'(Module,Culprit)))
; Directive \== (dynamic), '$lgt_pp_dynamic_'(Alias, _, _, _) ->
% clash with an earlier dynamic/1 directive (but allow duplicated dynamic/1 directives)
throw(permission_error(modify, dynamic_predicate, Culprit))
; true
).
% '$lgt_compile_reexport_directive'(+list, +atom, +compilation_context)
%
% auxiliary predicate for compiling module reexport/2 directives;
% the predicate renaming operator as/2 found on SWI-Prolog and YAP
% is also supported (iff we're compiling a module as an object)
'$lgt_compile_reexport_directive'([], _, _).
'$lgt_compile_reexport_directive'([Resource| Resources], Module, Ctx) :-
'$lgt_compile_reexport_directive_resource'(Resource, Module, Ctx),
'$lgt_compile_reexport_directive'(Resources, Module, Ctx).
'$lgt_compile_reexport_directive_resource'(op(Priority, Specifier, Operators), _, Ctx) :-
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
!,
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, l, File, Lines, Mode).
'$lgt_compile_reexport_directive_resource'(as(Original, Alias), Module, Ctx) :-
!,
'$lgt_compile_reexport_directive_resource'(':'(Original, Alias), Module, Ctx).
'$lgt_compile_reexport_directive_resource'(':'(Original, Alias), Module, Ctx) :-
'$lgt_valid_predicate_indicator'(Original, OriginalFunctor, Arity),
'$lgt_valid_predicate_indicator'(Alias, AliasFunctor, Arity),
!,
'$lgt_compile_logtalk_directive'(public(AliasFunctor/Arity), Ctx),
functor(OriginalHead, OriginalFunctor, Arity),
functor(AliasHead, AliasFunctor, Arity),
% unify arguments of original and alias
OriginalHead =.. [_| Args],
AliasHead =.. [_| Args],
% add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtxOriginal, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_comp_ctx'(AuxCtxAlias, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_clause'((OriginalHead :- Module::OriginalHead), AuxCtxOriginal),
'$lgt_compile_clause'((AliasHead :- Module::OriginalHead), AuxCtxAlias).
'$lgt_compile_reexport_directive_resource'(':'(Original, Alias), Module, Ctx) :-
'$lgt_valid_non_terminal_indicator'(Original, OriginalFunctor, Arity, _),
'$lgt_valid_predicate_indicator'(Alias, AliasFunctor, Arity),
!,
'$lgt_compile_logtalk_directive'(public(AliasFunctor//Arity), Ctx),
functor(OriginalHead, OriginalFunctor, Arity),
functor(AliasHead, AliasFunctor, Arity),
% unify arguments of original and alias
OriginalHead =.. [_| Args],
AliasHead =.. [_| Args],
% add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtxOriginal, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_comp_ctx'(AuxCtxAlias, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_grammar_rule'((OriginalHead --> Module::OriginalHead), AuxCtxOriginal),
'$lgt_compile_grammar_rule'((AliasHead --> Module::OriginalHead), AuxCtxAlias).
'$lgt_compile_reexport_directive_resource'(Pred, Module, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, Functor, Arity),
!,
'$lgt_compile_logtalk_directive'(public(Pred), Ctx),
functor(Head, Functor, Arity),
% add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_clause'((Head :- Module::Head), AuxCtx).
'$lgt_compile_reexport_directive_resource'(NonTerminal, Module, Ctx) :-
'$lgt_valid_non_terminal_indicator'(NonTerminal, Functor, Arity, _),
!,
'$lgt_compile_logtalk_directive'(public(NonTerminal), Ctx),
functor(Head, Functor, Arity),
% add local definition
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, Lines, _),
'$lgt_comp_ctx'(AuxCtx, _, _, _, _, _, _, Prefix, _, _, ExCtx, compile(aux,_,_), _, Lines, _),
'$lgt_compile_grammar_rule'((Head --> Module::Head), AuxCtx).
'$lgt_compile_reexport_directive_resource'(Resource, _, _) :-
ground(Resource),
throw(type_error(predicate_indicator, Resource)).
'$lgt_compile_reexport_directive_resource'(_, _, _) :-
throw(instantiation_error).
% auxiliary predicate for compiling module's meta predicate directives
% into Logtalk ones by translating the meta-argument specifiers
'$lgt_compile_module_meta_predicate_directive'([Template| Templates], [ConvertedTemplate| ConvertedTemplates]) :-
'$lgt_compile_module_meta_predicate_directive_template'(Template, ConvertedTemplate),
'$lgt_compile_module_meta_predicate_directive'(Templates, ConvertedTemplates).
'$lgt_compile_module_meta_predicate_directive'([], []).
'$lgt_compile_module_meta_predicate_directive_template'(':'(Module,Template), ':'(Module,ConvertedTemplate)) :-
!,
'$lgt_check'(module_identifier, Module),
'$lgt_compile_module_meta_predicate_directive_template'(Template, ConvertedTemplate).
'$lgt_compile_module_meta_predicate_directive_template'(Template, ConvertedTemplate) :-
'$lgt_check'(callable, Template),
Template =.. [Functor| Args],
'$lgt_prolog_to_logtalk_meta_argument_specifiers'(Args, ConvertedArgs),
ConvertedTemplate =.. [Functor| ConvertedArgs].
% '$lgt_check_for_duplicated_directive'(@callable, @callable)
'$lgt_check_for_duplicated_directive'(TDirective, Directive) :-
( '$lgt_pp_directive_'(TDirective),
'$lgt_compiler_flag'(duplicated_directives, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(duplicated_directives),
duplicated_directive(File, Lines, Type, Entity, Directive)
)
; true
).
% auxiliary predicate for translating Prolog dialect meta-argument
% predicate specifiers into Logtalk specifiers
'$lgt_prolog_to_logtalk_meta_argument_specifiers'([], []).
'$lgt_prolog_to_logtalk_meta_argument_specifiers'([Arg| Args], [TArg| TArgs]) :-
( \+ ground(Arg) ->
throw(instantiation_error)
; '$lgt_prolog_to_logtalk_meta_argument_specifier_hook'(Arg, TArg) ->
true
; '$lgt_prolog_to_logtalk_meta_argument_specifier'(Arg, TArg) ->
true
; throw(domain_error(meta_argument_specifier, Arg))
),
'$lgt_prolog_to_logtalk_meta_argument_specifiers'(Args, TArgs).
% goals and closures are denoted by integers >= 0
'$lgt_prolog_to_logtalk_meta_argument_specifier'(N, N) :-
integer(N),
!.
% Prolog to Logtalk notation; this is fragile due to the lack of standardization
'$lgt_prolog_to_logtalk_meta_argument_specifier'((:), (::)).
% mixed-up notation or overriding meta-predicate template being used
'$lgt_prolog_to_logtalk_meta_argument_specifier'((::), (::)).
% predicate indicator
'$lgt_prolog_to_logtalk_meta_argument_specifier'((/), (/)).
% non-terminal indicator
'$lgt_prolog_to_logtalk_meta_argument_specifier'((//), (//)).
% list of goals/closures
'$lgt_prolog_to_logtalk_meta_argument_specifier'([N], [N]) :-
integer(N),
!.
% list of predicate indicators
'$lgt_prolog_to_logtalk_meta_argument_specifier'([/], [/]) :-
!.
% list of non-terminal indicators
'$lgt_prolog_to_logtalk_meta_argument_specifier'([//], [//]) :-
!.
% goal with possible existential variables qualification
'$lgt_prolog_to_logtalk_meta_argument_specifier'((^), (^)).
% instantiation modes (non meta-arguments)
'$lgt_prolog_to_logtalk_meta_argument_specifier'((@), (*)).
'$lgt_prolog_to_logtalk_meta_argument_specifier'((+), (*)).
'$lgt_prolog_to_logtalk_meta_argument_specifier'((-), (*)).
'$lgt_prolog_to_logtalk_meta_argument_specifier'((?), (*)).
% non meta-arguments
'$lgt_prolog_to_logtalk_meta_argument_specifier'((*), (*)).
% '$lgt_compile_object_relations'(@list(term), @object_identifier, @compilation_context)
%
% compiles the relations of an object with other entities
'$lgt_compile_object_relations'([Relation| Relations], Obj, Ctx) :-
( var(Relation) ->
throw(instantiation_error)
; '$lgt_compile_object_relation'(Relation, Obj, Ctx) ->
true
; callable(Relation) ->
functor(Relation, Functor, Arity),
throw(domain_error(object_relation, Functor/Arity))
; throw(type_error(callable, Relation))
),
'$lgt_compile_object_relations'(Relations, Obj, Ctx).
'$lgt_compile_object_relations'([], _, _).
% '$lgt_compile_object_relation'(@nonvar, @object_identifier, @compilation_context)
%
% compiles a relation between an object (the last argument) with other entities
'$lgt_compile_object_relation'(implements(_), _, _) :-
'$lgt_pp_implemented_protocol_'(_, _, _, _, _),
throw(permission_error(repeat, entity_relation, implements/1)).
'$lgt_compile_object_relation'(implements(Ptcs), Obj, Ctx) :-
'$lgt_flatten_to_list'(Ptcs, FlattenedPtcs),
'$lgt_compile_implements_protocol_relation'(FlattenedPtcs, Obj, Ctx).
'$lgt_compile_object_relation'(imports(_), _, _) :-
'$lgt_pp_imported_category_'(_, _, _, _, _, _),
throw(permission_error(repeat, entity_relation, imports/1)).
'$lgt_compile_object_relation'(imports(Ctgs), Obj, Ctx) :-
'$lgt_flatten_to_list'(Ctgs, FlattenedCtgs),
'$lgt_compile_imports_category_relation'(FlattenedCtgs, Obj, Ctx).
'$lgt_compile_object_relation'(instantiates(_), _, _) :-
'$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _),
throw(permission_error(repeat, entity_relation, instantiates/1)).
'$lgt_compile_object_relation'(instantiates(Classes), Instance, Ctx) :-
'$lgt_flatten_to_list'(Classes, FlattenedClasses),
'$lgt_compile_instantiates_class_relation'(FlattenedClasses, Instance, Ctx).
'$lgt_compile_object_relation'(specializes(_), _, _) :-
'$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _),
throw(permission_error(repeat, entity_relation, specializes/1)).
'$lgt_compile_object_relation'(specializes(Superclasses), Class, Ctx) :-
'$lgt_flatten_to_list'(Superclasses, FlattenedSuperclasses),
'$lgt_compile_specializes_class_relation'(FlattenedSuperclasses, Class, Ctx).
'$lgt_compile_object_relation'(extends(_), _, _) :-
'$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(permission_error(repeat, entity_relation, extends/1)).
'$lgt_compile_object_relation'(extends(Parents), Prototype, Ctx) :-
'$lgt_flatten_to_list'(Parents, FlattenedParents),
'$lgt_compile_extends_object_relation'(FlattenedParents, Prototype, Ctx).
% '$lgt_compile_protocol_relations'(@list(term), @protocol_identifier, @compilation_context)
%
% compiles the relations of a protocol with other entities
'$lgt_compile_protocol_relations'([Relation| Relations], Ptc, Ctx) :-
( var(Relation) ->
throw(instantiation_error)
; '$lgt_compile_protocol_relation'(Relation, Ptc, Ctx) ->
true
; callable(Relation) ->
functor(Relation, Functor, Arity),
throw(domain_error(protocol_relation, Functor/Arity))
; throw(type_error(callable, Relation))
),
'$lgt_compile_protocol_relations'(Relations, Ptc, Ctx).
'$lgt_compile_protocol_relations'([], _, _).
% '$lgt_compile_protocol_relation'(@nonvar, @protocol_identifier, @compilation_context)
%
% compiles a relation between a protocol (the last argument) with other entities
'$lgt_compile_protocol_relation'(extends(_), _, _) :-
'$lgt_pp_extended_protocol_'(_, _, _, _, _),
throw(permission_error(repeat, entity_relation, extends/1)).
'$lgt_compile_protocol_relation'(extends(Ptcs), Ptc, Ctx) :-
'$lgt_flatten_to_list'(Ptcs, FlattenedPtcs),
'$lgt_compile_extends_protocol_relation'(FlattenedPtcs, Ptc, Ctx).
% '$lgt_compile_category_relations'(@list(term), @category_identifier, @compilation_context)
%
% compiles the relations of a category with other entities
'$lgt_compile_category_relations'([Relation| Relations], Ctg, Ctx) :-
( var(Relation) ->
throw(instantiation_error)
; '$lgt_compile_category_relation'(Relation, Ctg, Ctx) ->
true
; callable(Relation) ->
functor(Relation, Functor, Arity),
throw(domain_error(category_relation, Functor/Arity))
; throw(type_error(callable, Relation))
),
'$lgt_compile_category_relations'(Relations, Ctg, Ctx).
'$lgt_compile_category_relations'([], _, _).
% '$lgt_compile_category_relation'(@nonvar, @category_identifier, @compilation_context)
%
% compiles a relation between a category (the last argument) with other entities
'$lgt_compile_category_relation'(implements(_), _, _) :-
'$lgt_pp_implemented_protocol_'(_, _, _, _, _),
throw(permission_error(repeat, entity_relation, implements/1)).
'$lgt_compile_category_relation'(implements(Ptcs), Ctg, Ctx) :-
'$lgt_flatten_to_list'(Ptcs, FlattenedPtcs),
'$lgt_compile_implements_protocol_relation'(FlattenedPtcs, Ctg, Ctx).
'$lgt_compile_category_relation'(extends(_), _, _) :-
'$lgt_pp_extended_category_'(_, _, _, _, _, _),
throw(permission_error(repeat, entity_relation, extends/1)).
'$lgt_compile_category_relation'(extends(Ctgs), Ctg, Ctx) :-
'$lgt_flatten_to_list'(Ctgs, FlattenedCtgs),
'$lgt_compile_extends_category_relation'(FlattenedCtgs, Ctg, Ctx).
'$lgt_compile_category_relation'(complements(_), _, _) :-
'$lgt_pp_complemented_object_'(_, _, _, _, _),
throw(permission_error(repeat, entity_relation, complements/1)).
'$lgt_compile_category_relation'(complements(Objs), Ctg, Ctx) :-
'$lgt_flatten_to_list'(Objs, FlattenedObjs),
'$lgt_compile_complements_object_relation'(FlattenedObjs, Ctg, Ctx).
% '$lgt_compile_entity_info_directive'(@list(term), -list(pair))
%
% compiles the entity info/1 directive key-value pairs
'$lgt_compile_entity_info_directive'([Pair| Pairs], [TPair| TPairs]) :-
( '$lgt_valid_info_key_value_pair'(Pair, Key, Value) ->
'$lgt_compile_entity_info_directive_pair'(Key, Value, TPair),
'$lgt_compile_entity_info_directive'(Pairs, TPairs)
; % non-valid pair; generate an error
'$lgt_check'(key_value_info_pair, Pair)
).
'$lgt_compile_entity_info_directive'([], []).
% '$lgt_compile_entity_info_directive_pair'(+atom, @nonvar, -compound)
%
% compiles an entity info/1 directive key-value pair
'$lgt_compile_entity_info_directive_pair'(author, Author, author(Author)) :-
!,
( Author = {EntityName}, atom(EntityName) ->
true
; '$lgt_check'(atom_or_string, Author)
).
'$lgt_compile_entity_info_directive_pair'(comment, Comment, comment(Comment)) :-
!,
'$lgt_check'(atom_or_string, Comment).
'$lgt_compile_entity_info_directive_pair'(date, Date, date(Date)) :-
!,
( Date = Year-Month-Day ->
% ISO 8601 standard format
'$lgt_check'(non_negative_integer, Year),
'$lgt_check'(non_negative_integer, Month),
'$lgt_check'(non_negative_integer, Day)
; Date = Year/Month/Day ->
% deprecated format
'$lgt_check'(non_negative_integer, Year),
'$lgt_check'(non_negative_integer, Month),
'$lgt_check'(non_negative_integer, Day)
; throw(type_error(date, Date))
).
'$lgt_compile_entity_info_directive_pair'(parameters, Parameters, parameters(Parameters)) :-
!,
'$lgt_pp_entity_'(_, Entity, _),
functor(Entity, _, Arity),
'$lgt_check_entity_info_parameters'(Parameters, Entity, Parameters, 0, Arity).
'$lgt_compile_entity_info_directive_pair'(parnames, Parnames, parnames(Parnames)) :-
!,
'$lgt_pp_entity_'(_, Entity, _),
functor(Entity, _, Arity),
'$lgt_check_entity_info_parnames'(Parnames, Entity, Parnames, 0, Arity).
'$lgt_compile_entity_info_directive_pair'(remarks, Remarks, remarks(Remarks)) :-
!,
'$lgt_check'(list, Remarks),
( '$lgt_member'(Remark, Remarks), \+ '$lgt_valid_remark'(Remark) ->
throw(type_error(remark, Remark))
; true
).
'$lgt_compile_entity_info_directive_pair'(see_also, References, see_also(References)) :-
!,
'$lgt_check'(list(entity_identifier), References).
'$lgt_compile_entity_info_directive_pair'(version, Version, version(Version)) :-
!,
( Version = ':'(Major, ':'(Minor, Patch)) ->
'$lgt_check'(non_negative_integer, Major),
'$lgt_check'(non_negative_integer, Minor),
'$lgt_check'(non_negative_integer, Patch)
; % deprecated format
'$lgt_check'(atomic_or_string, Version)
).
'$lgt_compile_entity_info_directive_pair'(copyright, Copyright, copyright(Copyright)) :-
!,
( Copyright = {EntityName}, atom(EntityName) ->
true
; '$lgt_check'(atom_or_string, Copyright)
).
'$lgt_compile_entity_info_directive_pair'(license, License, license(License)) :-
!,
( License = {EntityName}, atom(EntityName) ->
true
; '$lgt_check'(atom_or_string, License)
).
% user-defined entity info pair; no checking
'$lgt_compile_entity_info_directive_pair'(Key, Value, TPair) :-
TPair =.. [Key, Value].
'$lgt_check_entity_info_parameters'([Pair| Pairs], Entity, Parameters, Counter0, Arity) :-
!,
( Pair = Name - Description ->
'$lgt_check'(atom_or_string, Name),
'$lgt_check'(atom_or_string, Description),
Counter1 is Counter0 + 1,
'$lgt_check_entity_info_parameters'(Pairs, Entity, Parameters, Counter1, Arity)
; throw(type_error(pair, Pair))
).
'$lgt_check_entity_info_parameters'([], Entity, Parameters, Counter, Arity) :-
!,
( Counter =:= Arity ->
true
; throw(consistency_error(same_number_of_parameters, Entity, Parameters))
).
'$lgt_check_entity_info_parameters'(_, _, Parameters, _, _) :-
throw(type_error(list, Parameters)).
'$lgt_check_entity_info_parnames'([Name| Names], Entity, Parnames, Counter0, Arity) :-
!,
'$lgt_check'(atom_or_string, Name),
Counter1 is Counter0 + 1,
'$lgt_check_entity_info_parnames'(Names, Entity, Parnames, Counter1, Arity).
'$lgt_check_entity_info_parnames'([], Entity, Parnames, Counter, Arity) :-
!,
( Counter =:= Arity ->
true
; throw(consistency_error(same_number_of_parameters, Entity, Parnames))
).
'$lgt_check_entity_info_parnames'(_, _, Parnames, _, _) :-
throw(type_error(list, Parnames)).
% '$lgt_compile_predicate_info_directive'(@list(term), +atom, +integer, -list(pair))
%
% compiles the predicate info/2 directive key-value pairs
'$lgt_compile_predicate_info_directive'([Pair| Pairs], Functor, Arity, [TPair| TPairs]) :-
( '$lgt_valid_info_key_value_pair'(Pair, Key, Value) ->
'$lgt_compile_predicate_info_directive_pair'(Key, Value, Functor, Arity, TPair),
'$lgt_compile_predicate_info_directive'(Pairs, Functor, Arity, TPairs)
; % non-valid pair; generate an error
'$lgt_check'(key_value_info_pair, Pair)
).
'$lgt_compile_predicate_info_directive'([], _, _, []).
% '$lgt_compile_predicate_info_directive_pair'(+atom, @nonvar, +atom, +integer, -compound)
%
% compiles a predicate info/2 directive key-value pair
'$lgt_compile_predicate_info_directive_pair'(allocation, Allocation, _, _, allocation(Allocation)) :-
!,
'$lgt_check'(atom, Allocation),
( '$lgt_valid_predicate_allocation'(Allocation) ->
true
; throw(domain_error(allocation, Allocation))
).
'$lgt_compile_predicate_info_directive_pair'(arguments, Arguments, Functor, Arity, arguments(Arguments)) :-
!,
'$lgt_check_predicate_info_arguments'(Arguments, Arguments, 0, Functor, Arity).
'$lgt_compile_predicate_info_directive_pair'(argnames, Argnames, Functor, Arity, argnames(Argnames)) :-
!,
'$lgt_check_predicate_info_argnames'(Argnames, Argnames, 0, Functor, Arity).
'$lgt_compile_predicate_info_directive_pair'(comment, Comment, _, _, comment(Comment)) :-
!,
'$lgt_check'(atom_or_string, Comment).
'$lgt_compile_predicate_info_directive_pair'(fails_if, FailsIf, _, _, fails_if(FailsIf)) :-
!,
'$lgt_check'(atom_or_string, FailsIf).
'$lgt_compile_predicate_info_directive_pair'(exceptions, Exceptions, _, _, exceptions(Exceptions)) :-
!,
'$lgt_check'(list, Exceptions),
( '$lgt_member'(Exception, Exceptions), \+ '$lgt_valid_predicate_exception'(Exception) ->
throw(type_error(exception, Exception))
; true
).
'$lgt_compile_predicate_info_directive_pair'(remarks, Remarks, _, _, remarks(Remarks)) :-
!,
'$lgt_check'(list, Remarks),
( '$lgt_member'(Remark, Remarks), \+ '$lgt_valid_remark'(Remark) ->
throw(type_error(remark, Remark))
; true
).
'$lgt_compile_predicate_info_directive_pair'(examples, Examples, Functor, Arity, examples(Examples)) :-
!,
'$lgt_check'(list, Examples),
( '$lgt_member'(Example, Examples), \+ '$lgt_valid_predicate_call_example'(Example, Functor, Arity) ->
throw(type_error(example, Example))
; true
).
'$lgt_compile_predicate_info_directive_pair'(redefinition, Redefinition, _, _, redefinition(Redefinition)) :-
!,
'$lgt_check'(atom, Redefinition),
( '$lgt_valid_predicate_redefinition'(Redefinition) ->
true
; throw(domain_error(redefinition, Redefinition))
).
'$lgt_compile_predicate_info_directive_pair'(see_also, References, _, _, see_also(References)) :-
!,
'$lgt_check'(list(predicate_or_non_terminal_indicator), References).
'$lgt_compile_predicate_info_directive_pair'(since, Version, _, _, since(Version)) :-
!,
( Version = ':'(Major, ':'(Minor, Patch)) ->
'$lgt_check'(non_negative_integer, Major),
'$lgt_check'(non_negative_integer, Minor),
'$lgt_check'(non_negative_integer, Patch)
; throw(domain_error(since, Version))
).
% user-defined predicate info pair; no checking
'$lgt_compile_predicate_info_directive_pair'(Key, Value, _, _, TPair) :-
TPair =.. [Key, Value].
'$lgt_check_predicate_info_arguments'([Pair| Pairs], Arguments, Counter0, Functor, Arity) :-
!,
( Pair = Name - Description ->
'$lgt_check'(atom_or_string, Name),
'$lgt_check'(atom_or_string, Description),
Counter1 is Counter0 + 1,
'$lgt_check_predicate_info_arguments'(Pairs, Arguments, Counter1, Functor, Arity)
; throw(type_error(pair, Pair))
).
'$lgt_check_predicate_info_arguments'([], Arguments, Counter, Functor, Arity) :-
!,
( Counter =:= Arity ->
true
; throw(consistency_error(same_number_of_arguments, Functor/Arity, Arguments))
).
'$lgt_check_predicate_info_arguments'(_, Arguments, _, _, _) :-
throw(type_error(list, Arguments)).
'$lgt_check_predicate_info_argnames'([Name| Names], Argnames, Counter0, Functor, Arity) :-
!,
'$lgt_check'(atom_or_string, Name),
Counter1 is Counter0 + 1,
'$lgt_check_predicate_info_argnames'(Names, Argnames, Counter1, Functor, Arity).
'$lgt_check_predicate_info_argnames'([], Argnames, Counter, Functor, Arity) :-
!,
( Counter =:= Arity ->
true
; throw(consistency_error(same_number_of_arguments, Functor/Arity, Argnames))
).
'$lgt_check_predicate_info_argnames'(_, Argnames, _, _, _) :-
throw(type_error(list, Argnames)).
% '$lgt_compile_grammar_rule'(+grammar_rule, +compilation_context)
'$lgt_compile_grammar_rule'(GrammarRule, Ctx) :-
catch(
'$lgt_dcg_rule'(GrammarRule, Clause, Ctx),
Error,
throw(error(Error, grammar_rule(GrammarRule)))
),
'$lgt_compile_clause'(Clause, Ctx).
% '$lgt_compile_clause'(+clause, +compilation_context)
%
% compiles a source file clause
'$lgt_compile_clause'(Clause, Ctx) :-
'$lgt_pp_entity_'(Type, Entity, Prefix),
% compiling an entity clause
( Type == protocol ->
% protocols cannot contain predicate definitions
throw(error(permission_error(define, predicate, Entity), clause(Clause)))
; true
),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, _, Mode, _, Lines, _),
catch(
'$lgt_compile_clause'(Clause, Entity, TClause, DClause, Ctx),
Error,
throw(error(Error, clause(Clause)))
),
% successful first stage compilation; save the source data information for
% use in the second compiler stage (where it might be required by calls
% to the logtalk_load_context/2 predicate during goal expansion or when
% checking for duplicated clauses)
( '$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines) ->
SourceData = sd(Term, VariableNames, Singletons, File, Lines)
; SourceData = nil
),
% check which compile clause to save (normal/optimal or debug) and
% if we have a clause defined by the user or an auxiliary clause
( '$lgt_compiler_flag'(debug, on) ->
( Mode = compile(aux,_,_) ->
assertz('$lgt_pp_entity_aux_clause_'(DClause))
; assertz('$lgt_pp_entity_term_'(DClause, SourceData, Lines))
)
; ( Mode = compile(aux,_,_) ->
assertz('$lgt_pp_entity_aux_clause_'(TClause))
; assertz('$lgt_pp_entity_term_'(TClause, SourceData, Lines))
)
),
!.
'$lgt_compile_clause'(Clause, _) :-
\+ '$lgt_pp_entity_'(_, _, _),
% clause occurs before an opening entity directive
!,
( '$lgt_pp_term_source_data_'(_, _, _, _, Lines) ->
true
; Lines = '-'(-1, -1)
),
% copy the clause unchanged to the generated Prolog file
assertz('$lgt_pp_prolog_term_'(Clause, Lines)).
'$lgt_compile_clause'(Clause, _) :-
% deal with unexpected clause translation failures
throw(error(system_error, clause(Clause))).
% '$lgt_compile_clause'(+clause, +entity_identifier, -clause, -clause, +compilation_context)
%
% compiles an entity clause into a normal clause and a debug clause
%
% in this first compiler stage only the clause heads are compiled, which
% allows collecting information about all entity defined predicates; the
% compilation of clause bodies is delayed to the compiler second stage to
% take advantage of the collected information to notably simplify handling
% of redefined built-in predicates
%
% in the case of a clause rule for a multifile predicate, the clause body
% is compiled in the context of the entity defining the clause; still, any
% calls to the parameter/2 method in the clause body will access parameters
% for the defining entity; parameters for the entity for which the clause
% is defined can be accessed through simple unification at the clause head
'$lgt_compile_clause'((Head :- Body), _, _, _, Ctx) :-
( '$lgt_variant'(Body, Head) ->
true
; Body = (Goal, _),
'$lgt_variant'(Goal, Head)
),
'$lgt_comp_ctx_term'(Ctx, Term),
callable(Term),
\+ functor(Term, (-->), 2),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(left_recursion, warning),
\+ '$lgt_pp_coinductive_'(Head, _, _, _, _, _, _, _, _),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(left_recursion),
left_recursion(File, Lines, Type, Entity, (Head :- Body))
),
fail.
'$lgt_compile_clause'((Head:-Body), Entity, TClause, DClause, Ctx) :-
!,
'$lgt_check'(callable, Head, clause((Head:-Body))),
'$lgt_head_meta_variables'(Head, MetaVars),
'$lgt_comp_ctx'(Ctx, Head, ExCtx, _, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, Mode, Stack, _, Term),
'$lgt_source_file_context'(Ctx, File, BeginLine-EndLine),
'$lgt_compile_head'(Head, PI, THead, Ctx),
( Head = {UserHead} ->
% clause for a multifile predicate in "user"
DHead = '$lgt_debug'(rule(Entity, user::UserHead, N, File, BeginLine), ExCtx),
'$lgt_comp_ctx'(BodyCtx, Head, ExCtx, _, _, _, _, Prefix, MetaVars, _, BodyExCtx, Mode, _, BeginLine-EndLine, Term),
'$lgt_execution_context_this_entity'(ExCtx, _, user),
% ensure that ::/1-2 and ^^/2 calls are compiled in the correct context
( '$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_execution_context'(BodyExCtx, Entity, Entity, Entity, Entity, [], [])
; % category
'$lgt_execution_context'(BodyExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack)
)
; Head = Other::OtherHead ->
% clause for an object or category multifile predicate
DHead = '$lgt_debug'(rule(Entity, Head, N, File, BeginLine), ExCtx),
'$lgt_comp_ctx'(BodyCtx, Head, ExCtx, _, _, _, _, Prefix, MetaVars, _, BodyExCtx, Mode, _, BeginLine-EndLine, Term),
term_variables(Other, OtherVars),
term_variables((OtherHead:-Body), ClauseVars),
'$lgt_intersection'(OtherVars, ClauseVars, CommonVars),
( CommonVars == [] ->
true
; % parametric entity sharing variables with the clause
'$lgt_execution_context_this_entity'(ExCtx, _, Other)
),
% ensure that ::/1-2 and ^^/2 calls are compiled in the correct context
( '$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_execution_context'(BodyExCtx, Entity, Entity, Entity, Entity, [], [])
; % category
'$lgt_execution_context'(BodyExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack)
)
; Head = ':'(_, _) ->
% clause for a module multifile predicate
DHead = '$lgt_debug'(rule(Entity, Head, N, File, BeginLine), ExCtx),
'$lgt_comp_ctx'(BodyCtx, Head, ExCtx, _, _, _, _, Prefix, MetaVars, _, BodyExCtx, Mode, _, BeginLine-EndLine, Term),
% ensure that ::/1-2 and ^^/2 calls are compiled in the correct context
( '$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_execution_context'(BodyExCtx, Entity, Entity, Entity, Entity, [], [])
; % category
'$lgt_execution_context'(BodyExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack)
)
; % clause for a local predicate
DHead = '$lgt_debug'(rule(Entity, Head, N, File, BeginLine), ExCtx),
BodyCtx = Ctx
),
( '$lgt_pp_dynamic_'(Head, _, _, _) ->
TClause = drule(THead, '$lgt_nop'(Body), Body, BodyCtx),
DClause = ddrule(THead, '$lgt_nop'(Body), DHead, Body, BodyCtx)
; TClause = srule(THead, Body, BodyCtx),
DClause = dsrule(THead, DHead, Body, BodyCtx)
),
'$lgt_clause_number'(PI, rule, File, BeginLine-EndLine, N).
'$lgt_compile_clause'(Fact, Entity, fact(TFact,Ctx), dfact(TFact,DHead,Ctx), Ctx) :-
'$lgt_check'(callable, Fact, clause(Fact)),
'$lgt_compile_head'(Fact, PI, TFact, Ctx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_source_file_context'(Ctx, File, BeginLine-EndLine),
( Fact = {UserFact} ->
% fact for a multifile predicate in "user"
DHead = '$lgt_debug'(fact(Entity, user::UserFact, N, File, BeginLine), ExCtx)
; Fact = Other::OtherFact ->
% fact for an entity multifile predicate
DHead = '$lgt_debug'(fact(Entity, Fact, N, File, BeginLine), ExCtx),
term_variables(Other, OtherVars),
term_variables(OtherFact, OtherFactVars),
'$lgt_intersection'(OtherVars, OtherFactVars, CommonVars),
( CommonVars == [] ->
true
; % parametric entity sharing variables with the fact
'$lgt_comp_ctx'(Ctx, _, _, Other, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Other)
)
; Fact = ':'(_, _) ->
% fact for a module multifile predicate
DHead = '$lgt_debug'(fact(Entity, Fact, N, File, BeginLine), ExCtx)
; var(ExCtx) ->
% local fact
DHead = '$lgt_debug'(fact(Entity, Fact, N, File, BeginLine), ExCtx)
; % parameter variables shared via the execution context
'$lgt_unify_head_thead_arguments'(Fact, TFact, ExCtx),
DHead = '$lgt_debug'(fact(Entity, Fact, N, File, BeginLine), ExCtx)
),
'$lgt_clause_number'(PI, fact, File, BeginLine-EndLine, N).
% '$lgt_clause_number'(@callable, +atom, +atom, +integer, -integer)
%
% returns the clause number for a compiled predicate; when the clause is the
% first one for the predicate, we also save the definition line in the source
% file (assuming that we're not compiling a clause for a dynamically created
% entity) for use with the reflection built-in predicates and methods
'$lgt_clause_number'(Other::Functor/Arity, fact, File, Lines, Clauses) :-
!,
% object or category multifile predicate
( retract('$lgt_pp_number_of_clauses_rules_'(Other, Functor, Arity, Clauses0, Rules)) ->
Clauses is Clauses0 + 1
; % first clause found for this predicate
Clauses = 1,
Rules = 0,
assertz('$lgt_pp_predicate_definition_location_'(Other, Functor, Arity, File, Lines))
),
assertz('$lgt_pp_number_of_clauses_rules_'(Other, Functor, Arity, Clauses, Rules)).
'$lgt_clause_number'(Other::Functor/Arity, rule, File, Lines, Clauses) :-
% object or category multifile predicate
( retract('$lgt_pp_number_of_clauses_rules_'(Other, Functor, Arity, Clauses0, Rules0)) ->
Clauses is Clauses0 + 1,
Rules is Rules0 + 1
; % first clause found for this predicate
Clauses = 1,
Rules = 1,
assertz('$lgt_pp_predicate_definition_location_'(Other, Functor, Arity, File, Lines))
),
assertz('$lgt_pp_number_of_clauses_rules_'(Other, Functor, Arity, Clauses, Rules)).
% module multifile predicate clause
'$lgt_clause_number'(':'(_, _), _, _, _, 0).
'$lgt_clause_number'({Head}, Kind, File, Lines, Clauses) :-
% pre-compiled predicate clause head
'$lgt_clause_number'(user::Head, Kind, File, Lines, Clauses).
'$lgt_clause_number'(Functor/Arity, fact, File, Lines, Clauses) :-
!,
% predicate clause for the entity being compiled
( retract('$lgt_pp_number_of_clauses_rules_'(Functor, Arity, Clauses0, Rules)) ->
Clauses is Clauses0 + 1
; % first clause found for this predicate
Clauses = 1,
Rules = 0,
assertz('$lgt_pp_predicate_definition_location_'(Functor, Arity, File, Lines))
),
assertz('$lgt_pp_number_of_clauses_rules_'(Functor, Arity, Clauses, Rules)).
'$lgt_clause_number'(Functor/Arity, rule, File, Lines, Clauses) :-
% predicate clause for the entity being compiled
( retract('$lgt_pp_number_of_clauses_rules_'(Functor, Arity, Clauses0, Rules0)) ->
Clauses is Clauses0 + 1,
Rules is Rules0 + 1
; % first clause found for this predicate
Clauses = 1,
Rules = 1,
assertz('$lgt_pp_predicate_definition_location_'(Functor, Arity, File, Lines))
),
assertz('$lgt_pp_number_of_clauses_rules_'(Functor, Arity, Clauses, Rules)).
% '$lgt_compile_head'(+callable, -callable, -callable, +compilation_context)
%
% compiles an entity clause head; also returns a term constructed from the
% head predicate indicator to be used as key to compute the clause number
% pre-compiled clause head (we only check for basic instantiation and type errors)
'$lgt_compile_head'({Head}, {Functor/Arity}, Head, _) :-
!,
'$lgt_check'(callable, Head),
functor(Head, Functor, Arity).
% not the first clause for this predicate; reuse the compiled head template
%
% we must ensure that Mode is the same to prevent that the auxiliary clauses
% created for uses/2 and use_module/2 directives would result in a cached
% template being reused for a conflicting user-defined predicate
'$lgt_compile_head'(Head, Functor/Arity, THead, Ctx) :-
'$lgt_pp_defines_predicate_'(Head, Functor/Arity, ExCtx, THead, Mode, Origin),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
!,
% only check for a discontiguous predicate for user-defined predicates
( '$lgt_pp_previous_predicate_'(Head, Origin) ->
true
; Origin == aux ->
true
; % clauses for the predicate are discontiguous
'$lgt_check_discontiguous_directive'(Head, Ctx)
).
% definition of dynamic predicates inside categories is not allowed
'$lgt_compile_head'(Head, _, _, _) :-
'$lgt_pp_category_'(_, _, _, _, _, _),
'$lgt_pp_dynamic_'(Head, _, _, _),
functor(Head, Functor, Arity),
throw(permission_error(define, dynamic_predicate, Functor/Arity)).
% redefinition of Logtalk built-in methods is not allowed
'$lgt_compile_head'(Head, _, _, _) :-
'$lgt_built_in_method'(Head, _, _, Flags),
Head \= _::_,
Head \= ':'(_, _),
% not a clause for a multifile predicate
Flags /\ 2 =\= 2,
% not a (user defined) dynamic built-in predicate
functor(Head, Functor, Arity),
throw(permission_error(modify, built_in_method, Functor/Arity)).
% conflict with a predicate specified in a uses/2 directive
'$lgt_compile_head'(Alias, _, _, _) :-
'$lgt_pp_uses_predicate_'(Obj, _, Alias, _, _, _),
functor(Alias, Functor, Arity),
throw(permission_error(modify, uses_object_predicate, Obj::Functor/Arity)).
% conflict with a predicate specified in a use_module/2 directive
'$lgt_compile_head'(Alias, _, _, _) :-
'$lgt_pp_use_module_predicate_'(Module, _, Alias, _, _, _),
functor(Alias, Functor, Arity),
throw(permission_error(modify, uses_module_predicate, ':'(Module,Functor/Arity))).
% definition of a reserved predicate without reference to the built-in protocol declaring it
'$lgt_compile_head'(Head, _, _, Ctx) :-
'$lgt_reserved_predicate_protocol'(Head, Protocol),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(general, warning),
\+ '$lgt_pp_module_'(_),
\+ '$lgt_pp_implemented_protocol_'(Protocol, _, _, _, _),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(general),
missing_reference_to_built_in_protocol(File, Lines, Type, Entity, Protocol)
),
fail.
% compile the head of a clause of another entity predicate (which we check if declared multifile)
'$lgt_compile_head'(Other::Head, _, _, _) :-
'$lgt_check'(entity_identifier, Other),
'$lgt_check'(callable, Head),
fail.
'$lgt_compile_head'(user::Head, user::Functor/Arity, Head, _) :-
!,
functor(Head, Functor, Arity),
( '$lgt_pp_directive_'(multifile(Functor/Arity)) ->
true
; '$lgt_pp_missing_multifile_directive_'(user::Functor/Arity, _, _) ->
true
; '$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_missing_multifile_directive_'(user::Functor/Arity, File, Lines))
).
'$lgt_compile_head'(Other::Head, Other::Functor/Arity, THead, Ctx) :-
!,
functor(Head, Functor, Arity),
'$lgt_entity_to_prefix'(Other, Prefix),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
( '$lgt_pp_directive_'(multifile(TFunctor/TArity)) ->
true
; throw(existence_error(directive, multifile(Other::Functor/Arity)))
),
functor(THead, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(Head, THead, ExCtx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
% compile the head of a clause of a module predicate (which we check if declared multifile)
'$lgt_compile_head'(':'(Module, Head), ':'(Module, Functor/Arity), THead, _) :-
!,
'$lgt_check'(callable, Head),
functor(Head, Functor, Arity),
( Module == user ->
THead = Head
; '$lgt_check'(module_identifier, Module),
THead = ':'(Module, Head)
),
( Module == user, '$lgt_pp_directive_'(multifile(Functor/Arity)) ->
true
; '$lgt_pp_directive_'(multifile(':'(Module, Functor/Arity))) ->
true
; '$lgt_pp_missing_multifile_directive_'(':'(Module,Functor/Arity), _, _) ->
true
; '$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_missing_multifile_directive_'(':'(Module,Functor/Arity), File, Lines))
).
% compile the head of a clause of a user defined predicate
'$lgt_compile_head'(Head, Functor/Arity, THead, Ctx) :-
% first clause for this predicate
functor(Head, Functor, Arity),
( '$lgt_pp_dynamic_'(Head, _, _, _),
\+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _) ->
% dynamic predicate without a scope directive; can be abolished if declared
% in an object and the abolish message sender is the object itself
'$lgt_add_ddef_clause'(Head, Functor, Arity, THead, Ctx)
; % static predicate and/or scoped dynamic predicate; cannot be abolished
'$lgt_add_def_clause'(Head, Functor, Arity, THead, Ctx)
).
% '$lgt_compile_body'(@term, @callable, -callable, -callable, +compilation_context)
%
% compiles an entity clause body
% runtime resolved meta-calls
'$lgt_compile_body'(Pred, Caller, TPred, '$lgt_debug'(goal(Pred, TPred), HeadExCtx), Ctx) :-
var(Pred),
!,
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, _, _, _, _, _, MetaVars, _, _, Mode, _, _, _),
'$lgt_check_for_meta_predicate_directive'(Mode, Head, Pred),
( '$lgt_member_var'(Pred, MetaVars) ->
TPred = '$lgt_metacall'(Pred, HeadExCtx, runtime)
; TPred = '$lgt_metacall'(Pred, HeadExCtx, local)
),
( Caller == rule,
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Pred, [call(Pred)])
)
; true
).
% compiler bypass control construct (opaque to cuts)
'$lgt_compile_body'({Pred}, _, _, _, Ctx) :-
callable(Pred),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
( Pred = call(Goal) ->
% redundant call/1 wrapper
Alternatives = [{Goal}]
; '$lgt_iso_spec_predicate'(Pred),
\+ '$lgt_built_in_method'(Pred, _, _, _),
% not a Logtalk built-in method that have a Prolog counterpart
\+ '$lgt_control_construct'(Pred),
\+ '$lgt_pp_defines_predicate_'(Pred, _, _, _, _, _),
% call to a standard Prolog predicate that is not being locally redefined,
Alternatives = [Pred]
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, {Pred}, Alternatives)
),
fail.
'$lgt_compile_body'({Pred}, _, TPred, '$lgt_debug'(goal({Pred}, TPred), ExCtx), Ctx) :-
!,
'$lgt_check'(var_or_callable, Pred),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
( var(Pred) ->
TPred = call(Pred),
'$lgt_check_for_meta_predicate_directive'(Mode, Head, Pred)
; Pred == ! ->
TPred = true
; '$lgt_cut_transparent_control_construct'(Pred) ->
% we need to keep the call/1 wrapper to preserve {}/1 cut-opaque semantics
TPred = call(Pred)
; TPred = Pred
).
% protect goal from further goal expansion
%
%'$lgt_compile_body'(@Pred, _, TPred, DPred, Ctx) :-
% !,
% '$lgt_check'(var_or_callable, Pred),
% '$lgt_comp_ctx_mode'(Ctx, Mode),
% ( Mode == runtime ->
% '$lgt_compile_body'(Pred, _, TPred, DPred, Ctx)
% ; Mode = compile(How, Cut, _),
% '$lgt_comp_ctx'(Ctx, Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, _, Stack, Lines, Term),
% '$lgt_comp_ctx'(NewCtx, Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, compile(How,Cut,[Pred]), Stack, Lines, Term),
% '$lgt_compile_body'(Pred, _, TPred, DPred, NewCtx)
% ).
% goal expansion (only applied at compile time)
'$lgt_compile_body'(Pred, Caller, TPred, DPred, Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, compile(How,Cut,ExpandedGoals), Stack, Lines, Term),
'$lgt_push_if_new'(ExpandedGoals, Pred, NewExpandedGoals),
'$lgt_expand_file_goal'(Pred, ExpandedPred),
Pred \== ExpandedPred,
!,
'$lgt_comp_ctx'(NewCtx, Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, compile(How,Cut,NewExpandedGoals), Stack, Lines, Term),
'$lgt_compile_body'(ExpandedPred, Caller, TPred, DPred, NewCtx).
% message delegation (send a message while preserving the original sender)
'$lgt_compile_body'([Goal], _, _, _, _) :-
'$lgt_check'(callable, Goal),
\+ functor(Goal, (::), 2),
throw(domain_error(message_sending_goal, Goal)).
'$lgt_compile_body'([Alias::Pred], Caller, TPred, DPred, Ctx) :-
callable(Alias),
'$lgt_pp_object_alias_'(Obj, Alias, Ctx, _, _),
!,
'$lgt_compile_body'([Obj::Pred], Caller, TPred, DPred, Ctx).
'$lgt_compile_body'([Obj::Pred], _, TPred, '$lgt_debug'(goal([Obj::Pred], TPred), ExCtx), Ctx) :-
!,
% as delegation keeps the original sender, we cannot use a recursive call
% to the '$lgt_compile_body'/4 predicate to compile the ::/2 goal as that
% would reset the sender to "this"
'$lgt_comp_ctx'(Ctx, Head, _, _, Sender, _, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, Mode, Stack, Lines, Term),
( '$lgt_pp_meta_predicate_'(Head, _, _, _) ->
'$lgt_execution_context'(ExCtx, _, Sender, _, _, MetaCallCtx, _),
'$lgt_comp_ctx'(NewCtx, Head, _, _, Sender, Sender, Self, Prefix, MetaVars, _, MetaCallCtx, Mode, Stack, Lines, Term)
; '$lgt_comp_ctx'(Ctx, Head, _, _, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, Mode, Stack, Lines, Term),
'$lgt_execution_context'(ExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack),
'$lgt_comp_ctx'(NewCtx, Head, _, _, Sender, Sender, Self, Prefix, MetaVars, MetaCallCtx, NewExCtx, Mode, Stack, Lines, Term),
'$lgt_execution_context'(NewExCtx, Entity, Sender, Sender, Self, MetaCallCtx, Stack)
),
'$lgt_compiler_flag'(events, Events),
'$lgt_compile_message_to_object'(Pred, Obj, TPred0, Events, NewCtx),
% ensure that this control construct cannot be used to break object encapsulation
TPred = (Obj \= Sender -> TPred0; throw(error(permission_error(access,object,Sender), logtalk([Obj::Pred],ExCtx)))).
% existential quantifier outside bagof/3 and setof/3 calls
'$lgt_compile_body'(_^_, _, _, _, _) :-
% in some unusual cases, the user may be defining a (^)/2 predicate ...
\+ '$lgt_pp_defines_predicate_'(_^_, _, _, _, _, _),
% ... but otherwise (^)/2 cannot be used outside bagof/3 and setof/3 calls
throw(existence_error(procedure, (^)/2)).
% control constructs
'$lgt_compile_body'((Pred, _), _, _, _, Ctx) :-
callable(Pred),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, compile(_,_,_), _, _, _),
callable(Head),
% ignore multifile predicates
Head \= ':'(_, _),
Head \= _::_,
functor(Pred, Functor, Arity),
functor(Head, Functor, Arity),
% non-tail recursive predicate definition
( '$lgt_pp_non_tail_recursive_predicate_'(Functor, Arity, _, _) ->
true
; '$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_non_tail_recursive_predicate_'(Functor, Arity, File, Lines))
),
fail.
'$lgt_compile_body'((Pred1, Pred2), Caller, (TPred1, TPred2), (DPred1, DPred2), Ctx) :-
!,
'$lgt_compile_body'(Pred1, Caller, TPred1, DPred1, Ctx),
( TPred1 == repeat,
% check if the repeat loop ends with a cut if compiling a source file
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, compile(How,_,ExpandedGoals), Stack, Lines, Term) ->
'$lgt_comp_ctx'(NewCtx, Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, compile(How,Cut,ExpandedGoals), Stack, Lines, Term),
'$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, NewCtx),
( var(Cut),
% no cut found; note that this lint check is limited to conjunctions where
% the left side is a call to repeat/0 and the right side contains a cut
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, repeat, reason(repeat(Head)))
) ->
true
; % cut found
true
)
; '$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, Ctx)
).
'$lgt_compile_body'((If -> _; _), _, _, _, Ctx) :-
nonvar(If),
once((If = (Term1 = Term2); If = (Term1 \= Term2))),
once((number(Term1); number(Term2))),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(arithmetic_expressions),
suspicious_call(File, Lines, Type, Entity, If, reason(comparing_numbers_using_unification))
),
fail.
'$lgt_compile_body'((If -> _; _), _, _, _, Ctx) :-
nonvar(If),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
( If == ! ->
Message = suspicious_cut_in_if_then_else(File, Lines, Type, Entity, Head)
; If = (Goal, _), Goal == !,
Message = suspicious_cut_in_if_then_else(File, Lines, Type, Entity, Head, If)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(conditionals), Message),
fail.
'$lgt_compile_body'((If -> _; _), _, _, _, Ctx) :-
nonvar(If),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
If = (Term1 = Term2),
( var(Term1), ground(Term2) ->
true
; ground(Term1), var(Term2)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(conditionals),
suspicious_if_then_else_test(File, Lines, Type, Entity, Head, If)
),
fail.
'$lgt_compile_body'((IfThen; Else), Caller, (TIf -> TThen; TElse), (DIf -> DThen; DElse), Ctx) :-
nonvar(IfThen),
IfThen = (If -> Then),
!,
'$lgt_compile_body'(If, meta, TIf, DIf, Ctx),
'$lgt_compile_body'(Then, Caller, TThen, DThen, Ctx),
'$lgt_compile_body'(Else, Caller, TElse, DElse, Ctx).
'$lgt_compile_body'((SoftCut; _), _, _, _, Ctx) :-
nonvar(SoftCut),
SoftCut = '*->'(If, _),
nonvar(If),
'$lgt_predicate_property'('*->'(_, _), built_in),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
( If == ! ->
Message = suspicious_cut_in_soft_cut(File, Lines, Type, Entity, Head)
; If = (Goal, _), Goal == !,
Message = suspicious_cut_in_soft_cut(File, Lines, Type, Entity, Head, If)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(conditionals), Message),
fail.
'$lgt_compile_body'((SoftCut; _), _, _, _, Ctx) :-
nonvar(SoftCut),
SoftCut = '*->'(If, _),
nonvar(If),
'$lgt_predicate_property'('*->'(_, _), built_in),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
If = (Term1 = Term2),
( var(Term1), ground(Term2) ->
true
; ground(Term1), var(Term2)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(conditionals),
suspicious_soft_cut_test(File, Lines, Type, Entity, Head, If)
),
fail.
'$lgt_compile_body'((SoftCut; Else), _, ('*->'(TIf, TThen); TElse), ('*->'(DIf, DThen); DElse), Ctx) :-
nonvar(SoftCut),
SoftCut = '*->'(If, Then),
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_compile_body'(If, meta, TIf, DIf, Ctx),
'$lgt_compile_body'(Then, Caller, TThen, DThen, Ctx),
'$lgt_compile_body'(Else, Caller, TElse, DElse, Ctx).
'$lgt_compile_body'((Pred1; Pred2), _, _, _, Ctx) :-
nonvar(Pred1),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(disjunctions, warning),
( Pred1 == ! ->
Message = suspicious_cut_in_disjunction(File, Lines, Type, Entity, Head)
; Pred1 = (Goal, _), Goal == !,
Message = suspicious_cut_in_disjunction(File, Lines, Type, Entity, Head, (Pred1; Pred2))
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(disjunctions), Message),
fail.
'$lgt_compile_body'((Pred1; Pred2), _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(disjunctions, warning),
'$lgt_comp_ctx_term'(Ctx, (Head :- (Pred11; Pred22))),
(Pred1; Pred2) == (Pred11; Pred22),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(disjunctions),
disjunction_as_body(File, Lines, Type, Entity, Head, (Pred1; Pred2))
),
fail.
'$lgt_compile_body'((Pred1; Pred2), Caller, (TPred1; TPred2), (DPred1; DPred2), Ctx) :-
!,
'$lgt_compile_body'(Pred1, Caller, TPred10, DPred10, Ctx),
'$lgt_fix_disjunction_left_side'(TPred10, TPred1),
'$lgt_fix_disjunction_left_side'(DPred10, DPred1),
'$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, Ctx).
'$lgt_compile_body'('*->'(Pred1, Pred2), Caller, TPred2, DPred2, Ctx) :-
Pred1 == otherwise,
'$lgt_predicate_property'(otherwise, built_in),
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_construct(File, Lines, Type, Entity, '*->'(Pred1, Pred2), Pred2)
)
; true
),
'$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, Ctx).
'$lgt_compile_body'('*->'(If, _), _, _, _, Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
nonvar(If),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
( If == ! ->
Message = suspicious_cut_in_soft_cut(File, Lines, Type, Entity, Head)
; If = (Goal, _), Goal == !,
Message = suspicious_cut_in_soft_cut(File, Lines, Type, Entity, Head, If)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(conditionals), Message),
fail.
'$lgt_compile_body'('*->'(If, _), _, _, _, Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
nonvar(If),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
If = (Term1 = Term2),
( var(Term1), ground(Term2) ->
true
; ground(Term1), var(Term2)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(conditionals),
suspicious_soft_cut_test(File, Lines, Type, Entity, Head, If)
),
fail.
'$lgt_compile_body'('*->'(Pred1, Pred2), _, _, _, Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
callable(Pred1),
callable(Pred2),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(conditionals),
missing_else_part(File, Lines, Type, Entity, '*->'(Pred1, Pred2))
),
fail.
'$lgt_compile_body'('*->'(Pred1, Pred2), Caller, '*->'(TPred1, TPred2), '*->'(DPred1, DPred2), Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_compile_body'(Pred1, meta, TPred1, DPred1, Ctx),
'$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, Ctx).
'$lgt_compile_body'((Pred1 -> Pred2), Caller, TPred2, DPred2, Ctx) :-
Pred1 == otherwise,
'$lgt_predicate_property'(otherwise, built_in),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_construct(File, Lines, Type, Entity, (Pred1 -> Pred2), Pred2)
)
; true
),
'$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, Ctx).
'$lgt_compile_body'((If -> _), _, _, _, Ctx) :-
nonvar(If),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
( If == ! ->
Message = suspicious_cut_in_if_then_else(File, Lines, Type, Entity, Head)
; If = (Goal, _), Goal == !,
Message = suspicious_cut_in_if_then_else(File, Lines, Type, Entity, Head, If)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(conditionals), Message),
fail.
'$lgt_compile_body'((If -> _), _, _, _, Ctx) :-
nonvar(If),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
If = (Term1 = Term2),
( var(Term1), ground(Term2) ->
true
; ground(Term1), var(Term2)
),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_comp_ctx_head'(Ctx, Head),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(conditionals),
suspicious_if_then_else_test(File, Lines, Type, Entity, Head, If)
),
fail.
'$lgt_compile_body'((Pred1 -> Pred2), _, _, _, Ctx) :-
callable(Pred1),
callable(Pred2),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(conditionals, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(conditionals),
missing_else_part(File, Lines, Type, Entity, (Pred1 -> Pred2))
),
fail.
'$lgt_compile_body'((Pred1 -> Pred2), Caller, (TPred1 -> TPred2), (DPred1 -> DPred2), Ctx) :-
!,
'$lgt_compile_body'(Pred1, meta, TPred1, DPred1, Ctx),
'$lgt_compile_body'(Pred2, Caller, TPred2, DPred2, Ctx).
'$lgt_compile_body'(not(Pred), Caller, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(not(_)),
\+ '$lgt_pp_defines_predicate_'(not(_), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, (not)/1, (\+)/1)
)
; true
),
'$lgt_compile_body'(\+ Pred, Caller, TPred, DPred, Ctx).
'$lgt_compile_body'(fail_if(Pred), Caller, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(fail_if(_)),
\+ '$lgt_pp_defines_predicate_'(fail_if(_), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, fail_if/1, (\+)/1)
)
; true
),
'$lgt_compile_body'(\+ Pred, Caller, TPred, DPred, Ctx).
'$lgt_compile_body'(\+ Pred, _, _, _, Ctx) :-
callable(Pred),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_negated_goal_alternative'(Pred, Alt),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, \+ Pred, [Alt])
),
fail.
'$lgt_compile_body'(\+ Pred, _, \+ TPred, '$lgt_debug'(goal(\+ Pred, \+ DPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Pred, meta, TPred, DPred, Ctx).
% warning on cuts on clauses for multifile predicates
'$lgt_compile_body'(!, _, _, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, compile(_,_,_), _, Lines, _),
callable(Head),
( Head = _::_ ->
true
; Head = ':'(_, _) ->
true
; '$lgt_pp_multifile_'(Head, _, _, _)
),
% clause for a multifile predicate
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, !, reason(multifile(Head)))
),
fail.
% warning on cuts on clauses with variable aliasing in the head
'$lgt_compile_body'(!, _, _, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, compile(_,_,_), _, Lines, _),
'$lgt_compiler_flag'(steadfastness, warning),
'$lgt_variable_aliasing'(Head),
functor(Head, Functor, Arity),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_defines_non_terminal_'(Functor, Arity2, Arity) ->
'$lgt_print_message'(
warning(steadfastness),
possible_non_steadfast_non_terminal(File, Lines, Type, Entity, Functor//Arity2)
)
; '$lgt_print_message'(
warning(steadfastness),
possible_non_steadfast_predicate(File, Lines, Type, Entity, Functor/Arity)
)
),
fail.
% when processing the debug event, the compiled goal is meta-called but
% this would make the cut local, changing the semantics of the user code;
% the solution is to use a conjunction for the debug goal of the debug
% event with a cut
'$lgt_compile_body'(!, _, !, ('$lgt_debug'(goal(!, true), ExCtx), !), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
( Mode == runtime ->
true
; % remember that we found a cut to enable lint checks on repeat loops
Mode = compile(_, true, _)
).
'$lgt_compile_body'(true, _, true, '$lgt_debug'(goal(true, true), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(fail, _, fail, '$lgt_debug'(goal(fail, fail), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(false, _, false, '$lgt_debug'(goal(false, false), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(repeat, _, repeat, '$lgt_debug'(goal(repeat, repeat), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(call(Goal), _, _, _, Ctx) :-
callable(Goal),
\+ '$lgt_cut_transparent_control_construct'(Goal),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, call(Goal), [Goal])
),
fail.
'$lgt_compile_body'(call(Goal), _, TPred, '$lgt_debug'(goal(call(Goal), DPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
( functor(TGoal, '$lgt_metacall', _) ->
TPred = TGoal,
DPred = DGoal
; '$lgt_cut_transparent_control_construct'(TGoal) ->
% we need to keep the call/1 wrapper to preserve call/1 cut-opaque semantics
TPred = call(TGoal),
DPred = call(DGoal)
; TPred = TGoal,
DPred = DGoal
).
'$lgt_compile_body'('$lgt_callN'(Closure, ExtraArgs), _, _, _, Ctx) :-
var(Closure),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, MetaVars, _, _, _, _, _, _),
nonvar(Head),
% ignore multifile predicates
Head \= ':'(_, _),
Head \= _::_,
'$lgt_pp_meta_predicate_'(Head, Meta, _, _),
% we're compiling a clause for a meta-predicate
once('$lgt_member_var'(Closure, MetaVars)),
% the closure is a meta-argument
'$lgt_length'(ExtraArgs, 0, NExtraArgs),
Meta =.. [_| MetaArgs],
% check that the call/N call complies with the meta-predicate declaration
'$lgt_not_same_meta_arg_extra_args'(MetaArgs, MetaVars, Closure, NExtraArgs),
% generate the call/N meta template
findall('*', '$lgt_between'(1, NExtraArgs, _), Stars),
CallN =.. [call, NExtraArgs| Stars],
throw(consistency_error(same_closure_specification, CallN, Meta)).
'$lgt_compile_body'('$lgt_callN'(Closure, ExtraArgs), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, _, _, _, _, _, MetaVars, _, _, Mode, _, _, _),
( var(Closure) ->
% we're compiling a runtime meta-call
'$lgt_check_for_meta_predicate_directive'(Mode, Head, Closure),
( '$lgt_member_var'(Closure, MetaVars) ->
TPred = '$lgt_metacall'(Closure, ExtraArgs, HeadExCtx, runtime)
; TPred = '$lgt_metacall'(Closure, ExtraArgs, HeadExCtx, local)
)
; '$lgt_extend_closure'(Closure, ExtraArgs, Goal, Ctx),
\+ (functor(Goal, call, Arity), Arity >= 2) ->
% not a call to call/2-N itself; safe to compile it
'$lgt_compile_body'(Goal, meta, TPred0, _, Ctx),
( '$lgt_cut_transparent_control_construct'(TPred0) ->
% we need to keep the call/1 wrapper to preserve call/2-N cut-opaque semantics
TPred = call(TPred0)
; TPred = TPred0
)
; % runtime resolved meta-call (e.g. a lambda expression)
TPred = '$lgt_metacall'(Closure, ExtraArgs, HeadExCtx, local)
),
CallN =.. [call, Closure| ExtraArgs],
DPred = '$lgt_debug'(goal(CallN, TPred), HeadExCtx).
'$lgt_compile_body'(once(Goal), _, (TGoal -> true), '$lgt_debug'(goal(once(Goal), (DGoal -> true)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx).
'$lgt_compile_body'(ignore(Goal), _, (TGoal -> true; true), '$lgt_debug'(goal(ignore(Goal), (DGoal -> true; true)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx).
% error handling and throwing predicates
'$lgt_compile_body'(catch(Goal, Catcher, Recovery), _, _, _, Ctx) :-
var(Catcher),
term_variables(Recovery, Variables),
\+ '$lgt_member_var'(Catcher, Variables),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(catchall_catch, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, _, _, _),
\+ (
'$lgt_member'(_=Var, VariableNames),
Catcher == Var
),
% assume that Catcher is an anonymous variable
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(catchall_catch),
catchall_catch(File, Lines, Type, Entity, catch(Goal, Catcher, Recovery))
),
fail.
'$lgt_compile_body'(catch(Goal, Catcher, Recovery), _, catch(TGoal, Catcher, TRecovery), '$lgt_debug'(goal(catch(Goal, Catcher, Recovery), catch(DGoal, Catcher, DRecovery)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
'$lgt_compile_body'(Recovery, meta, TRecovery, DRecovery, Ctx).
'$lgt_compile_body'(throw(Error), _, throw(Error), '$lgt_debug'(goal(throw(Error), throw(Error)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(Pred, _, TPred, DPred, Ctx) :-
'$lgt_built_in_error_method'(Pred),
!,
'$lgt_compile_error_method'(Pred, TPred, DPred, Ctx).
% type testing (only lint warnings)
'$lgt_compile_body'(var(Var), _, _, _, Ctx) :-
var(Var),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, Singletons, _, _),
'$lgt_anonymous_or_singleton_variable'(Var, VariableNames, Singletons),
% var/1 predicate argument is either an anonymous or a
% singleton variable and thus can never be bound
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_true(File, Lines, Type, Entity, var(Var))
),
fail.
'$lgt_compile_body'(nonvar(Var), _, _, _, Ctx) :-
var(Var),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, Singletons, _, _),
'$lgt_anonymous_or_singleton_variable'(Var, VariableNames, Singletons),
% nonvar/1 predicate argument is either an anonymous or a
% singleton variable and thus can never be bound
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_false(File, Lines, Type, Entity, nonvar(Var))
),
fail.
'$lgt_compile_body'(ground(Ground), _, _, _, Ctx) :-
\+ ground(Ground),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
term_variables(Ground, Variables),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, Singletons, _, _),
'$lgt_anonymous_or_singleton_variables'(Variables, VariableNames, Singletons),
% all variables in the ground/1 predicate argument are either
% anonymous or singleton variables and thus can never be bound
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_false(File, Lines, Type, Entity, ground(Ground))
),
fail.
% term comparison (only lint warnings)
'$lgt_compile_body'(Exp1 == Exp2, _, _, _, Ctx) :-
once((float(Exp1); float(Exp2))),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(arithmetic_expressions),
suspicious_call(File, Lines, Type, Entity, Exp1 == Exp2, reason(float_comparison))
),
fail.
'$lgt_compile_body'(Exp1 \== Exp2, _, _, _, Ctx) :-
once((float(Exp1); float(Exp2))),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(arithmetic_expressions),
suspicious_call(File, Lines, Type, Entity, Exp1 \== Exp2, reason(float_comparison))
),
fail.
% unification (only lint warnings)
'$lgt_compile_body'(Term1 = Term2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_prolog_feature'(coinduction, supported),
% backend provides minimal support for cyclic terms; calling the next goal
% while using a backend that doesn't support cyclic terms would end badly
\+ \+ (
Term1 = Term2,
\+ acyclic_term(Term1)
),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Term1 = Term2, reason(cyclic_terms))
),
fail.
'$lgt_compile_body'(Term1 = Term2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
( Term1 \= Term2 ->
% unification fails; further instantiation of Term1 or Term2 will not make it succeed
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_false(File, Lines, Type, Entity, Term1 = Term2)
)
; \+ ground(Term1),
\+ ground(Term2),
\+ \+ (
term_variables(Term1-Term2, Vars0),
unify_with_occurs_check(Term1, Term2),
term_variables(Term1-Term2, Vars),
Vars0 == Vars
),
% unification will not bind any variables in the unified terms
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Term1 = Term2, reason(no_variable_bindings_after_unification))
)
),
fail.
'$lgt_compile_body'(unify_with_occurs_check(Term1, Term2), _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
( \+ unify_with_occurs_check(Term1, Term2) ->
% unification fails; further instantiation of Term1 or Term2 will not make it succeed
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_false(File, Lines, Type, Entity, unify_with_occurs_check(Term1, Term2))
)
; \+ ground(Term1),
\+ ground(Term2),
\+ \+ (
term_variables(Term1-Term2, Vars0),
unify_with_occurs_check(Term1, Term2),
term_variables(Term1-Term2, Vars),
Vars0 == Vars
),
% unification will not bind any variables in the unified terms
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, unify_with_occurs_check(Term1, Term2), reason(no_variable_bindings_after_unification))
)
),
fail.
'$lgt_compile_body'(Term1 \= Term2, _, _, _, Ctx) :-
once((number(Term1); number(Term2))),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(arithmetic_expressions),
suspicious_call(File, Lines, Type, Entity, Term1 \= Term2, reason(comparing_numbers_using_unification))
),
fail.
'$lgt_compile_body'(Term1 \= Term2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
Term1 \= Term2,
% goal succeeds; further instantiation of Term1 or Term2 will not make it fail
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_true(File, Lines, Type, Entity, Term1 \= Term2)
),
fail.
% atomic term processing predicates (only lint warnings)
'$lgt_compile_body'(atom_concat(Prefix, Var, Atom), _, _, _, Ctx) :-
atom(Prefix),
var(Var),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, _, _, _),
\+ (
'$lgt_member'(_=Var0, VariableNames),
Var0 == Var
),
% assume that Var is an anonymous variable
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, atom_concat(Prefix, Var, Atom), [sub_atom(Atom, 0, _, _, Prefix)])
),
fail.
% term creation and decomposition predicates (only lint warnings)
'$lgt_compile_body'(Term =.. List, _, _, _, Ctx) :-
'$lgt_is_list'(List),
% closed list (compound term with know arity)
List = [Functor| _],
nonvar(Functor),
% with a bound functor
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
ListTerm =.. List,
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Term =.. List, [Term = ListTerm])
),
fail.
'$lgt_compile_body'(Term =.. List, _, _, _, Ctx) :-
nonvar(List),
List = [Functor| Args],
var(Args),
% open list (compound term with unknown arity)
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, _, _, _),
once((
'$lgt_member'(_=Functor0, VariableNames),
Functor0 == Functor
)),
% assume that functor is not an anonymous variable
\+ (
'$lgt_member'(_=Args0, VariableNames),
Args0 == Args
),
% assume that the list tail is an anonymous variable
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Term =.. List, [functor(Term, Functor, _)])
),
fail.
'$lgt_compile_body'(Term =.. List, _, _, _, Ctx) :-
nonvar(List),
List = [Functor| Args],
var(Functor),
nonvar(Args),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, _, _, _),
\+ (
'$lgt_member'(_=Functor0, VariableNames),
Functor0 == Functor
),
% assume that the functor argument is an anonymous variable
'$lgt_position_relevant_argument_pairs'(Args, 1, VariableNames, [N-Arg], open, Tail),
\+ (
'$lgt_member'(_=Tail0, VariableNames),
Tail0 == Tail
),
% assume a single bound argument or non-anonymous variable argument in the compound term
% arguments; we also require an open list with an anonymous variable as tail for this as
% otherwise the =../2 call may also being used e.g. to verify the compound term arity
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Term =.. List, [arg(N, Term, Arg)])
),
fail.
% lambda expressions
'$lgt_compile_body'(Parameters>>Lambda, _, _, _, Ctx) :-
'$lgt_check_lambda_expression'(Parameters>>Lambda, Ctx),
fail.
'$lgt_compile_body'(Free/Parameters>>Lambda, Caller, TPred, DPred, Ctx) :-
nonvar(Parameters),
!,
( Parameters == [] ->
'$lgt_compile_body'(Free/Lambda, Caller, TPred, DPred, Ctx)
; throw(representation_error(lambda_parameters))
).
'$lgt_compile_body'(Free/Parameters>>Lambda, _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% lambda expressions are handled as meta-calls
TPred = '$lgt_metacall'(Free/Parameters>>Lambda, [], ExCtx, local),
DPred = '$lgt_debug'(goal(Free/Parameters>>Lambda, TPred), ExCtx).
'$lgt_compile_body'(Parameters>>Lambda, Caller, TPred, DPred, Ctx) :-
nonvar(Parameters),
!,
( Parameters == [] ->
'$lgt_compile_body'(Lambda, Caller, TPred, DPred, Ctx)
; throw(representation_error(lambda_parameters))
).
'$lgt_compile_body'(Parameters>>Lambda, _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% lambda expressions are handled as meta-calls
TPred = '$lgt_metacall'(Parameters>>Lambda, [], ExCtx, local),
DPred = '$lgt_debug'(goal(Parameters>>Lambda, TPred), ExCtx).
'$lgt_compile_body'(Free/Lambda, _, _, _, Ctx) :-
'$lgt_check_lambda_expression'(Free/Lambda, Ctx),
fail.
'$lgt_compile_body'(Free/Lambda, Caller, TPred, DPred, Ctx) :-
nonvar(Free),
nonvar(Lambda),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_comp_ctx_meta_vars'(Ctx, []) ->
% generate an auxiliary predicate to replace the lambda expression
'$lgt_generate_aux_predicate_functor'('_lambda_', Functor),
( Free = {Terms} ->
'$lgt_conjunction_to_list'(Terms, Args)
; Args = []
),
Head =.. [Functor| Args],
'$lgt_compile_aux_clauses'([(Head :- Lambda)]),
'$lgt_compile_body'(Head, Caller, TPred, DPred, Ctx)
; % either runtime translation or the lambda expression appears in the
% body of a meta-predicate clause
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Lambda, Caller, TLambda, DLambda, Ctx),
TPred = '$lgt_lambda'(Free, TLambda),
DPred = '$lgt_debug'(goal(Free/Lambda, '$lgt_lambda'(Free, DLambda)), ExCtx)
).
'$lgt_compile_body'(Free/Lambda, _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% lambda expressions are handled as meta-calls
TPred = '$lgt_metacall'(Free/Lambda, [], ExCtx, local),
DPred = '$lgt_debug'(goal(Free/Lambda, TPred), ExCtx).
% built-in meta-predicates
'$lgt_compile_body'(bagof(Term, QGoal, List), _, _, _, Ctx) :-
callable(QGoal),
\+ ground(Term),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_decompose_quantified_body'(QGoal, _, Goal),
term_variables(Goal, GoalVariables),
term_variables(Term, TermVariables),
'$lgt_intersection'(TermVariables, GoalVariables, []),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, bagof(Term,QGoal,List), reason(no_shared_variables(bagof)))
),
fail.
'$lgt_compile_body'(bagof(_, QGoal, _), _, _, _, Ctx) :-
callable(QGoal),
QGoal = _^_,
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_missing_existential_variables'(QGoal, [Variable| Variables], Goal),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, QGoal, reason(existential_variables([Variable|Variables],Goal)))
),
fail.
'$lgt_compile_body'(bagof(_, QGoal, _), _, _, _, Ctx) :-
callable(QGoal),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_singleton_variables_in_meta_argument'(QGoal, Singletons, Ctx),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, QGoal, reason(singleton_variables(bagof/3,QGoal,Singletons)))
),
fail.
'$lgt_compile_body'(bagof(Term, QGoal, List), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, _, _, _, _, _, MetaVars, _, ExCtx, Mode, _, _, _),
( var(QGoal) ->
% runtime meta-call
'$lgt_check_for_meta_predicate_directive'(Mode, Head, QGoal),
( '$lgt_member_var'(QGoal, MetaVars) ->
TPred = '$lgt_bagof'(Term, QGoal, List, HeadExCtx, runtime)
; TPred = '$lgt_bagof'(Term, QGoal, List, HeadExCtx, local)
),
DPred = '$lgt_debug'(goal(bagof(Term, QGoal, List), TPred), HeadExCtx)
; % compile time local call
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_quantified_body'(QGoal, meta, TGoal, DGoal, Ctx),
TPred = bagof(Term, TGoal, List),
DPred = '$lgt_debug'(goal(bagof(Term, QGoal, List), bagof(Term, DGoal, List)), ExCtx)
).
'$lgt_compile_body'(findall(Term, Goal, List), _, _, _, Ctx) :-
nonvar(Goal),
\+ ground(Term),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
term_variables(Term, TermVariables),
term_variables(Goal, GoalVariables),
'$lgt_intersection'(TermVariables, GoalVariables, []),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, _, _, _),
once((
'$lgt_member'(_=Term0, VariableNames),
Term0 == Term
)),
% assume that Term is not an anonymous variable
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, findall(Term,Goal,List), reason(no_shared_variables(findall)))
),
fail.
'$lgt_compile_body'(findall(Term, Goal, List), _, _, _, Ctx) :-
var(Term),
var(List),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, _, _, _),
\+ (
'$lgt_member'(_=List0, VariableNames),
List0 == List
),
% assume that List is an anonymous variable
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, findall(Term, Goal, List), [(Goal, fail; true)])
),
fail.
'$lgt_compile_body'(findall(Term, Goal, List), _, findall(Term, TGoal, List), '$lgt_debug'(goal(findall(Term, Goal, List), findall(Term, DGoal, List)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx).
'$lgt_compile_body'(findall(Term, Goal, List, Tail), _, _, _, Ctx) :-
nonvar(Goal),
\+ ground(Term),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
term_variables(Term, TermVariables),
term_variables(Goal, GoalVariables),
'$lgt_intersection'(TermVariables, GoalVariables, []),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, findall(Term,Goal,List,Tail), reason(no_shared_variables(findall)))
),
fail.
'$lgt_compile_body'(findall(Term, Goal, List, Tail), _, findall(Term, TGoal, List, Tail), '$lgt_debug'(goal(findall(Term, Goal, List, Tail), findall(Term, DGoal, List, Tail)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx).
'$lgt_compile_body'(forall(Gen, Test), _, _, _, Ctx) :-
callable(Gen),
callable(Test),
\+ ground(Gen),
\+ ground(Test),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
term_variables(Gen, GenVariables),
term_variables(Test, TestVariables),
'$lgt_intersection'(GenVariables, TestVariables, []),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, forall(Gen,Test), reason(no_shared_variables(forall)))
),
fail.
'$lgt_compile_body'(forall(Gen, Test), _, \+ (TGen, \+ TTest), '$lgt_debug'(goal(forall(Gen, Test), \+ (DGen, \+ DTest)), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Gen, meta, TGen, DGen, Ctx),
'$lgt_compile_body'(Test, meta, TTest, DTest, Ctx).
'$lgt_compile_body'(setof(Term, QGoal, List), _, _, _, Ctx) :-
callable(QGoal),
\+ ground(Term),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_decompose_quantified_body'(QGoal, _, Goal),
term_variables(Goal, GoalVariables),
term_variables(Term, TermVariables),
'$lgt_intersection'(TermVariables, GoalVariables, []),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, setof(Term,QGoal,List), reason(no_shared_variables(setof)))
),
fail.
'$lgt_compile_body'(setof(_, QGoal, _), _, _, _, Ctx) :-
callable(QGoal),
QGoal = _^_,
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_missing_existential_variables'(QGoal, [Variable| Variables], Goal),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, QGoal, reason(existential_variables([Variable|Variables],Goal)))
),
fail.
'$lgt_compile_body'(setof(_, QGoal, _), _, _, _, Ctx) :-
callable(QGoal),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_singleton_variables_in_meta_argument'(QGoal, Singletons, Ctx),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, QGoal, reason(singleton_variables(setof/3,QGoal,Singletons)))
),
fail.
'$lgt_compile_body'(setof(Term, QGoal, List), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, _, _, _, _, _, MetaVars, _, ExCtx, Mode, _, _, _),
( var(QGoal) ->
% runtime meta-call
'$lgt_check_for_meta_predicate_directive'(Mode, Head, QGoal),
( '$lgt_member_var'(QGoal, MetaVars) ->
TPred = '$lgt_setof'(Term, QGoal, List, HeadExCtx, runtime)
; TPred = '$lgt_setof'(Term, QGoal, List, HeadExCtx, local)
),
DPred = '$lgt_debug'(goal(setof(Term, QGoal, List), TPred), HeadExCtx)
; % compile time local call
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_quantified_body'(QGoal, meta, TGoal, DGoal, Ctx),
TPred = setof(Term, TGoal, List),
DPred = '$lgt_debug'(goal(setof(Term, QGoal, List), setof(Term, DGoal, List)), ExCtx)
).
% file compilation and loading predicates
'$lgt_compile_body'(logtalk_compile(Files), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
TPred = '$lgt_logtalk_compile'(Files, Directory, ExCtx),
DPred = '$lgt_debug'(goal(logtalk_compile(Files), TPred), ExCtx).
'$lgt_compile_body'(logtalk_compile(Files, Flags), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
TPred = '$lgt_logtalk_compile'(Files, Flags, Directory, ExCtx),
DPred = '$lgt_debug'(goal(logtalk_compile(Files, Flags), TPred), ExCtx).
'$lgt_compile_body'(logtalk_load(Files), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
TPred = '$lgt_logtalk_load'(Files, Directory, ExCtx),
DPred = '$lgt_debug'(goal(logtalk_load(Files), TPred), ExCtx).
'$lgt_compile_body'(logtalk_load(Files, Flags), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_pp_file_paths_flags_'(_, Directory, _, _, _),
TPred = '$lgt_logtalk_load'(Files, Flags, Directory, ExCtx),
DPred = '$lgt_debug'(goal(logtalk_load(Files, Flags), TPred), ExCtx).
% file compilation/loading context
'$lgt_compile_body'(logtalk_load_context(Key, Value), _, TPred, DPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
( var(Key) ->
TPred = '$lgt_logtalk_load_context'(Key, Value, ExCtx)
; '$lgt_valid_logtalk_load_context_key'(Key) ->
( nonvar(Head),
functor(Head, (:-), 1),
% compiling a directive an initialization/1 directive
'$lgt_logtalk_load_context_checked'(Key, Value) ->
% expand goal to support embedded applications where the compiled
% code may no longer be loaded using the Logtalk runtime
TPred = true
; TPred = '$lgt_logtalk_load_context_checked'(Key, Value)
)
; callable(Key) ->
throw(domain_error(logtalk_load_context_key, Key))
; throw(type_error(callable, Key))
),
DPred = '$lgt_debug'(goal(logtalk_load_context(Key, Value), TPred), ExCtx).
% entity enumeration predicates
'$lgt_compile_body'(current_object(Obj), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Obj) ->
TPred = '$lgt_current_object'(Obj, ExCtx)
; TPred = '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _)
),
DPred = '$lgt_debug'(goal(current_object(Obj), TPred), ExCtx).
'$lgt_compile_body'(current_protocol(Ptc), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Ptc) ->
TPred = '$lgt_current_protocol'(Ptc, ExCtx)
; TPred = '$lgt_current_protocol_'(Ptc, _, _, _, _)
),
DPred = '$lgt_debug'(goal(current_protocol(Ptc), TPred), ExCtx).
'$lgt_compile_body'(current_category(Ctg), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Ctg) ->
TPred = '$lgt_current_category'(Ctg, ExCtx)
; TPred = '$lgt_current_category_'(Ctg, _, _, _, _, _)
),
DPred = '$lgt_debug'(goal(current_category(Ctg), TPred), ExCtx).
% entity property predicates
'$lgt_compile_body'(object_property(Obj, Prop), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_object_property, Prop),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_object_property'(Obj, Prop, ExCtx),
DPred = '$lgt_debug'(goal(object_property(Obj, Prop), TPred), ExCtx).
'$lgt_compile_body'(protocol_property(Ptc, Prop), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_check'(var_or_protocol_property, Prop),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_protocol_property'(Ptc, Prop, ExCtx),
DPred = '$lgt_debug'(goal(protocol_property(Ptc, Prop), TPred), ExCtx).
'$lgt_compile_body'(category_property(Ctg, Prop), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_check'(var_or_category_property, Prop),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_category_property'(Ctg, Prop, ExCtx),
DPred = '$lgt_debug'(goal(category_property(Ctg, Prop), TPred), ExCtx).
% dynamic entity creation predicates
'$lgt_compile_body'(create_object(Obj, Relations, Directives, Clauses), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(list_or_partial_list, Relations),
'$lgt_check'(list_or_partial_list, Directives),
'$lgt_check'(list_or_partial_list, Clauses),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_create_object'(Obj, Relations, Directives, Clauses, ExCtx),
DPred = '$lgt_debug'(goal(create_object(Obj, Relations, Directives, Clauses), TPred), ExCtx).
'$lgt_compile_body'(create_protocol(Ptc, Relations, Directives), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_check'(list_or_partial_list, Relations),
'$lgt_check'(list_or_partial_list, Directives),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_create_protocol'(Ptc, Relations, Directives, ExCtx),
DPred = '$lgt_debug'(goal(create_protocol(Ptc, Relations, Directives), TPred), ExCtx).
'$lgt_compile_body'(create_category(Ctg, Relations, Directives, Clauses), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_check'(list_or_partial_list, Relations),
'$lgt_check'(list_or_partial_list, Directives),
'$lgt_check'(list_or_partial_list, Clauses),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_create_category'(Ctg, Relations, Directives, Clauses, ExCtx),
DPred = '$lgt_debug'(goal(create_category(Ctg, Relations, Directives, Clauses), TPred), ExCtx).
% dynamic entity abolishing predicates
'$lgt_compile_body'(abolish_object(Obj), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Obj) ->
TPred = '$lgt_abolish_object'(Obj, ExCtx)
; TPred = '$lgt_abolish_object_checked'(Obj, ExCtx)
),
DPred = '$lgt_debug'(goal(abolish_object(Obj), TPred), ExCtx).
'$lgt_compile_body'(abolish_protocol(Ptc), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Ptc) ->
TPred = '$lgt_abolish_protocol'(Ptc, ExCtx)
; TPred = '$lgt_abolish_protocol_checked'(Ptc, ExCtx)
),
DPred = '$lgt_debug'(goal(abolish_protocol(Ptc), TPred), ExCtx).
'$lgt_compile_body'(abolish_category(Ctg), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Ctg) ->
TPred = '$lgt_abolish_category'(Ctg, ExCtx)
; TPred = '$lgt_abolish_category_checked'(Ctg, ExCtx)
),
DPred = '$lgt_debug'(goal(abolish_category(Ctg), TPred), ExCtx).
% entity relations predicates
'$lgt_compile_body'(extends_protocol(Ptc, ExtPtc), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_check'(var_or_protocol_identifier, ExtPtc),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_extends_protocol'(Ptc, ExtPtc, ExCtx),
DPred = '$lgt_debug'(goal(extends_protocol(Ptc, ExtPtc), TPred), ExCtx).
'$lgt_compile_body'(extends_protocol(Ptc, ExtPtc, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_check'(var_or_protocol_identifier, ExtPtc),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_extends_protocol'(Ptc, ExtPtc, Scope, ExCtx),
DPred = '$lgt_debug'(goal(extends_protocol(Ptc, ExtPtc, Scope), TPred), ExCtx).
'$lgt_compile_body'(implements_protocol(ObjOrCtg, Ptc), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, ObjOrCtg),
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_implements_protocol'(ObjOrCtg, Ptc, ExCtx),
DPred = '$lgt_debug'(goal(implements_protocol(ObjOrCtg, Ptc), TPred), ExCtx).
'$lgt_compile_body'(implements_protocol(ObjOrCtg, Ptc, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, ObjOrCtg),
'$lgt_check'(var_or_protocol_identifier, Ptc),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_implements_protocol'(ObjOrCtg, Ptc, Scope, ExCtx),
DPred = '$lgt_debug'(goal(implements_protocol(ObjOrCtg, Ptc, Scope), TPred), ExCtx).
'$lgt_compile_body'(imports_category(Obj, Ctg), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_imports_category'(Obj, Ctg, ExCtx),
DPred = '$lgt_debug'(goal(imports_category(Obj, Ctg), TPred), ExCtx).
'$lgt_compile_body'(imports_category(Obj, Ctg, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_imports_category'(Obj, Ctg, Scope, ExCtx),
DPred = '$lgt_debug'(goal(imports_category(Obj, Ctg, Scope), TPred), ExCtx).
'$lgt_compile_body'(instantiates_class(Obj, Class), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_object_identifier, Class),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_instantiates_class'(Obj, Class, ExCtx),
DPred = '$lgt_debug'(goal(instantiates_class(Obj, Class), TPred), ExCtx).
'$lgt_compile_body'(instantiates_class(Obj, Class, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_object_identifier, Class),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_instantiates_class'(Obj, Class, Scope, ExCtx),
DPred = '$lgt_debug'(goal(instantiates_class(Obj, Class, Scope), TPred), ExCtx).
'$lgt_compile_body'(specializes_class(Class, Superclass), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Class),
'$lgt_check'(var_or_object_identifier, Superclass),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_specializes_class'(Class, Superclass, ExCtx),
DPred = '$lgt_debug'(goal(specializes_class(Class, Superclass), TPred), ExCtx).
'$lgt_compile_body'(specializes_class(Class, Superclass, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Class),
'$lgt_check'(var_or_object_identifier, Superclass),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_specializes_class'(Class, Superclass, Scope, ExCtx),
DPred = '$lgt_debug'(goal(specializes_class(Class, Superclass, Scope), TPred), ExCtx).
'$lgt_compile_body'(extends_category(Ctg, ExtCtg), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_check'(var_or_category_identifier, ExtCtg),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_extends_category'(Ctg, ExtCtg, ExCtx),
DPred = '$lgt_debug'(goal(extends_category(Ctg, ExtCtg), TPred), ExCtx).
'$lgt_compile_body'(extends_category(Ctg, ExtCtg, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Ctg),
'$lgt_check'(var_or_category_identifier, ExtCtg),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_extends_category'(Ctg, ExtCtg, Scope, ExCtx),
DPred = '$lgt_debug'(goal(extends_category(Ctg, ExtCtg, Scope), TPred), ExCtx).
'$lgt_compile_body'(extends_object(Prototype, Parent), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Prototype),
'$lgt_check'(var_or_object_identifier, Parent),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_extends_object'(Prototype, Parent, ExCtx),
DPred = '$lgt_debug'(goal(extends_object(Prototype, Parent), TPred), ExCtx).
'$lgt_compile_body'(extends_object(Prototype, Parent, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, Prototype),
'$lgt_check'(var_or_object_identifier, Parent),
'$lgt_check'(var_or_scope, Scope),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_extends_object'(Prototype, Parent, Scope, ExCtx),
DPred = '$lgt_debug'(goal(extends_object(Prototype, Parent, Scope), TPred), ExCtx).
'$lgt_compile_body'(complements_object(Category, Object), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_category_identifier, Category),
'$lgt_check'(var_or_object_identifier, Object),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_complements_object'(Category, Object, ExCtx),
DPred = '$lgt_debug'(goal(complements_object(Category, Object), TPred), ExCtx).
'$lgt_compile_body'(conforms_to_protocol(ObjOrCtg, Protocol), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, ObjOrCtg),
'$lgt_check'(var_or_protocol_identifier, Protocol),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_conforms_to_protocol'(ObjOrCtg, Protocol, ExCtx),
DPred = '$lgt_debug'(goal(conforms_to_protocol(ObjOrCtg, Protocol), TPred), ExCtx).
'$lgt_compile_body'(conforms_to_protocol(ObjOrCtg, Protocol, Scope), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_object_identifier, ObjOrCtg),
'$lgt_check'(var_or_protocol_identifier, Protocol),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_conforms_to_protocol'(ObjOrCtg, Protocol, Scope, ExCtx),
DPred = '$lgt_debug'(goal(conforms_to_protocol(ObjOrCtg, Protocol), TPred), ExCtx).
% events predicates
'$lgt_compile_body'(current_event(Event, Obj, Msg, Sender, Monitor), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_event, Event),
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_callable, Msg),
'$lgt_check'(var_or_object_identifier, Sender),
'$lgt_check'(var_or_object_identifier, Monitor),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_current_event'(Event, Obj, Msg, Sender, Monitor, ExCtx),
DPred = '$lgt_debug'(goal(current_event(Event, Obj, Msg, Sender, Monitor), TPred), ExCtx).
'$lgt_compile_body'(define_events(Event, Obj, Msg, Sender, Monitor), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_event, Event),
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_callable, Msg),
'$lgt_check'(var_or_object_identifier, Sender),
'$lgt_check'(var_or_object_identifier, Monitor),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_define_events'(Event, Obj, Msg, Sender, Monitor, ExCtx),
DPred = '$lgt_debug'(goal(define_events(Event, Obj, Msg, Sender, Monitor), TPred), ExCtx).
'$lgt_compile_body'(abolish_events(Event, Obj, Msg, Sender, Monitor), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_event, Event),
'$lgt_check'(var_or_object_identifier, Obj),
'$lgt_check'(var_or_callable, Msg),
'$lgt_check'(var_or_object_identifier, Sender),
'$lgt_check'(var_or_object_identifier, Monitor),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_abolish_events'(Event, Obj, Msg, Sender, Monitor, ExCtx),
DPred = '$lgt_debug'(goal(abolish_events(Event, Obj, Msg, Sender, Monitor), TPred), ExCtx).
% multi-threading meta-predicates
'$lgt_compile_body'(threaded(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded(Goals), _, TGoal, '$lgt_debug'(goal(threaded(Goals), TGoal), ExCtx), Ctx) :-
var(Goals),
!,
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, _, _, _, _, _, MetaVars, _, _, Mode, _, _, _),
'$lgt_check_for_meta_predicate_directive'(Mode, Head, Goals),
( '$lgt_member_var'(Goals, MetaVars) ->
TGoal = '$lgt_threaded'(Goals, HeadExCtx, runtime)
; TGoal = '$lgt_threaded'(Goals, HeadExCtx, local)
),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(threaded(Goals), _, MTGoals, '$lgt_debug'(goal(threaded(Goals), MDGoals), ExCtx), Ctx) :-
!,
'$lgt_compile_body'(Goals, meta, TGoals, DGoals, Ctx),
'$lgt_compile_threaded_call'(TGoals, MTGoals),
'$lgt_compile_threaded_call'(DGoals, MDGoals),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(threaded_call(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_call(Goal, Tag), _, MTGoal, '$lgt_debug'(goal(threaded_call(Goal, Tag), MDGoal), ExCtx), Ctx) :-
!,
'$lgt_check'(var, Tag),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
MTGoal = '$lgt_threaded_call_tagged'(Goal, TGoal, ExCtx, Tag),
MDGoal = '$lgt_threaded_call_tagged'(Goal, DGoal, ExCtx, Tag).
'$lgt_compile_body'(threaded_call(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_call(Goal), _, MTGoal, '$lgt_debug'(goal(threaded_call(Goal), MDGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
MTGoal = '$lgt_threaded_call'(Goal, TGoal, ExCtx),
MDGoal = '$lgt_threaded_call'(Goal, DGoal, ExCtx).
'$lgt_compile_body'(threaded_once(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_once(Goal, Tag), _, MTGoal, '$lgt_debug'(goal(threaded_once(Goal, Tag), MDGoal), ExCtx), Ctx) :-
!,
'$lgt_check'(var, Tag),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
MTGoal = '$lgt_threaded_once_tagged'(Goal, TGoal, ExCtx, Tag),
MDGoal = '$lgt_threaded_once_tagged'(Goal, DGoal, ExCtx, Tag).
'$lgt_compile_body'(threaded_once(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_once(Goal), _, MTGoal, '$lgt_debug'(goal(threaded_once(Goal), MDGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
MTGoal = '$lgt_threaded_once'(Goal, TGoal, ExCtx),
MDGoal = '$lgt_threaded_once'(Goal, DGoal, ExCtx).
'$lgt_compile_body'(threaded_ignore(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_ignore(Goal), _, MTGoal, '$lgt_debug'(goal(threaded_ignore(Goal), MDGoal), ExCtx), Ctx) :-
!,
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
MTGoal = '$lgt_threaded_ignore'(Goal, TGoal, ExCtx),
MDGoal = '$lgt_threaded_ignore'(Goal, DGoal, ExCtx).
'$lgt_compile_body'(threaded_exit(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_exit(Goal, Tag), _, TGoal, '$lgt_debug'(goal(threaded_exit(Goal, Tag), TGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% compile the goal just for type-checking and collecting source data
'$lgt_compile_body'(Goal, meta, _, _, Ctx),
TGoal = '$lgt_threaded_exit_tagged'(Goal, ExCtx, Tag).
'$lgt_compile_body'(threaded_exit(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_exit(Goal), _, TGoal, '$lgt_debug'(goal(threaded_exit(Goal), TGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% compile the goal just for type-checking and collecting source data
'$lgt_compile_body'(Goal, meta, _, _, Ctx),
TGoal = '$lgt_threaded_exit'(Goal, ExCtx).
'$lgt_compile_body'(threaded_peek(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_peek(Goal, Tag), _, TGoal, '$lgt_debug'(goal(threaded_peek(Goal, Tag), TGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% compile the goal just for type-checking and collecting source data
'$lgt_compile_body'(Goal, meta, _, _, Ctx),
TGoal = '$lgt_threaded_peek_tagged'(Goal, ExCtx, Tag).
'$lgt_compile_body'(threaded_peek(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_peek(Goal), _, TGoal, '$lgt_debug'(goal(threaded_peek(Goal), TGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
% compile the goal just for type-checking and collecting source data
'$lgt_compile_body'(Goal, meta, _, _, Ctx),
TGoal = '$lgt_threaded_peek'(Goal, ExCtx).
'$lgt_compile_body'(threaded_cancel(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_cancel(Tag), _, TGoal, '$lgt_debug'(goal(threaded_cancel(Tag), TGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TGoal = '$lgt_threaded_cancel_tagged'(Tag, ExCtx).
'$lgt_compile_body'(threaded_engine_create(_, _, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_create(AnswerTemplate, Goal, Engine), _, MTGoal, '$lgt_debug'(goal(threaded_engine_create(AnswerTemplate, Goal, Engine), MDGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(Goal, meta, TGoal, DGoal, Ctx),
MTGoal = '$lgt_threaded_engine_create'(AnswerTemplate, Goal, TGoal, ExCtx, Engine),
MDGoal = '$lgt_threaded_engine_create'(AnswerTemplate, Goal, DGoal, ExCtx, Engine).
'$lgt_compile_body'(threaded_engine_self(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_self(Engine), _, MTGoal, '$lgt_debug'(goal(threaded_engine_self(Engine), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
MTGoal = '$lgt_threaded_engine_self'(This, Engine),
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _).
'$lgt_compile_body'(threaded_engine(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine(Engine), _, MTGoal, '$lgt_debug'(goal(threaded_engine(Engine), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
MTGoal = '$lgt_current_engine'(This, Engine),
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _).
'$lgt_compile_body'(threaded_engine_next(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_next(Engine, Answer), _, MTGoal, '$lgt_debug'(goal(threaded_engine_next_reified(Engine, Answer), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
MTGoal = '$lgt_threaded_engine_next'(Engine, Answer, ExCtx).
'$lgt_compile_body'(threaded_engine_next_reified(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_next_reified(Engine, Answer), _, MTGoal, '$lgt_debug'(goal(threaded_engine_next_reified(Engine, Answer), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
MTGoal = '$lgt_threaded_engine_next_reified'(Engine, Answer, ExCtx).
'$lgt_compile_body'(threaded_engine_yield(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_yield(Answer), _, MTGoal, '$lgt_debug'(goal(threaded_engine_yield(Answer), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
MTGoal = '$lgt_threaded_engine_yield'(Answer, This),
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _).
'$lgt_compile_body'(threaded_engine_post(_, _), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_post(Engine, Message), _, MTGoal, '$lgt_debug'(goal(threaded_engine_post(Engine, Message), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
MTGoal = '$lgt_threaded_engine_post'(Engine, Message, ExCtx).
'$lgt_compile_body'(threaded_engine_fetch(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_fetch(Message), _, MTGoal, '$lgt_debug'(goal(threaded_engine_fetch(Message), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
MTGoal = '$lgt_threaded_engine_fetch'(Message, This),
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _).
'$lgt_compile_body'(threaded_engine_destroy(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_engine_destroy(Engine), _, MTGoal, '$lgt_debug'(goal(threaded_engine_destroy(Engine), MTGoal), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
MTGoal = '$lgt_threaded_engine_destroy'(Engine, ExCtx).
'$lgt_compile_body'(threaded_wait(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_wait(Msg), _, MTPred, '$lgt_debug'(goal(threaded_wait(Msg), MTPred), ExCtx), Ctx) :-
!,
( '$lgt_pp_entity_'(Type, _, Prefix) ->
true
; Type = object % <2 call
),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, _, _),
( nonvar(Head),
'$lgt_pp_synchronized_'(Head, Mutex, _, _) ->
( Type == object ->
% we're compiling an object predicate
MTPred = '$lgt_threaded_wait_synch'(Mutex, Msg, Prefix)
; % we're compiling a category predicate
'$lgt_comp_ctx_this'(Ctx, This),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
MTPred = '$lgt_threaded_wait_synch_ctg'(Mutex, Msg, This)
)
; ( Type == object ->
% we're compiling an object predicate
MTPred = '$lgt_threaded_wait'(Msg, Prefix)
; % we're compiling a category predicate
'$lgt_comp_ctx_this'(Ctx, This),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
MTPred = '$lgt_threaded_wait_ctg'(Msg, This)
)
).
'$lgt_compile_body'(threaded_notify(_), _, _, _, _) :-
\+ '$lgt_pp_threaded_',
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, _, _),
throw(resource_error(threads)).
'$lgt_compile_body'(threaded_notify(Msg), _, MTPred, '$lgt_debug'(goal(threaded_notify(Msg), MTPred), ExCtx), Ctx) :-
!,
( '$lgt_pp_entity_'(Type, _, Prefix) ->
true
; Type = object % <2 call
),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, _, _),
( Type == object ->
% we're compiling an object predicate
MTPred = '$lgt_threaded_notify'(Msg, Prefix)
; % we're compiling a category predicate
'$lgt_comp_ctx_this'(Ctx, This),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
MTPred = '$lgt_threaded_notify_ctg'(Msg, This)
).
% message sending
'$lgt_compile_body'(Alias::Pred, _, TPred, '$lgt_debug'(goal(Alias::Pred, TPred), ExCtx), Ctx) :-
callable(Alias),
'$lgt_pp_object_alias_'(Obj, Alias, Ctx, _, _),
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compiler_flag'(events, Events),
'$lgt_compile_message_to_object'(Pred, Obj, TPred, Events, Ctx).
'$lgt_compile_body'(Obj::Pred, _, TPred, '$lgt_debug'(goal(Obj::Pred, TPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compiler_flag'(events, Events),
'$lgt_compile_message_to_object'(Pred, Obj, TPred, Events, Ctx).
'$lgt_compile_body'(::Pred, _, TPred, '$lgt_debug'(goal(::Pred, TPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_message_to_self'(Pred, TPred, Ctx).
'$lgt_compile_body'(^^Pred, _, TPred, '$lgt_debug'(goal(^^Pred, TPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_super_call'(Pred, TPred, Ctx).
% context-switching
'$lgt_compile_body'(Obj<
% no scope directive
TPred = '$lgt_call_in_this'(Pred, ExCtx)
; TPred = '$lgt_call_in_this_checked'(Pred, ExCtx)
).
'$lgt_compile_body'(@Pred, Caller, TPred, DPred, Ctx) :-
!,
'$lgt_check'(callable, Pred),
'$lgt_compile_body'(Pred, Caller, TPred, DPred, Ctx).
% calling explicitly qualified module predicates
'$lgt_compile_body'(':'(_, Callable), Caller, TPred, DPred, Ctx) :-
nonvar(Callable),
Callable = ':'(Module, Pred),
% in a module predicate call with multiple prefixes (e.g. m1:m2:m3:goal),
% only the one that immediately precedes the predicate is relevant
!,
'$lgt_compile_body'(':'(Module, Pred), Caller, TPred, DPred, Ctx).
'$lgt_compile_body'(':'(Alias, Pred), Caller, TPred, '$lgt_debug'(goal(':'(Alias, Pred), TPred), ExCtx), Ctx) :-
atom(Alias),
'$lgt_pp_module_alias_'(Module, Alias, Ctx, _, _),
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
'$lgt_compile_body'(':'(Module, Pred), Caller, TPred, _, Ctx).
'$lgt_compile_body'(':'(Module, Pred), _, _, _, Ctx) :-
'$lgt_prolog_feature'(modules, unsupported),
\+ '$lgt_pp_module_'(_),
% not compiling a module as an object
% likely typo where a message sending goal is intended
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, ':'(Module, Pred), [Module::Pred])
),
fail.
'$lgt_compile_body'(':'(Module, Pred), _, _, _, Ctx) :-
atom(Module),
callable(Pred),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
logtalk_linter_hook(':'(Module, Pred), Flag, File, Lines, Type, Entity, Warning),
nonvar(Flag),
'$lgt_valid_flag'(Flag),
'$lgt_compiler_flag'(Flag, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(Flag), Warning),
fail.
'$lgt_compile_body'(':'(Module, Pred), Caller, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Pred),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::Pred, Caller, TPred, DPred, Ctx)
; var(Module) ->
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = ':'(Module, Pred),
DPred = '$lgt_debug'(goal(':'(Module, Pred), TPred), ExCtx)
; var(Pred) ->
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = ':'(Module, Pred),
DPred = '$lgt_debug'(goal(':'(Module, Pred), TPred), ExCtx)
; \+ '$lgt_prolog_built_in_database_predicate'(Pred),
% the meta-predicate templates for the backend Prolog database predicates are usually
% not usable from Logtalk due the ambiguity of the ":" meta-argument qualifier but they
% pose no problems when operating in a module database; in this particular case, the
% explicit-qualified call can be compiled as-is
( '$lgt_pp_meta_predicate_'(':'(Module, Pred), ':'(Module, Meta), _, _)
% we're either overriding the original meta-predicate template or working around a
% backend Prolog compiler limitation in providing access to meta-predicate templates
; catch('$lgt_predicate_property'(':'(Module, Pred), meta_predicate(Meta)), _, fail)
) ->
% we're compiling a call to a module meta-predicate
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_module_predicate'(Mode, Module, Pred, Pred, Head),
Pred =.. [Functor| Args],
Meta =.. [Functor| MArgs],
'$lgt_prolog_to_logtalk_meta_argument_specifiers'(MArgs, CMArgs),
( '$lgt_member'(CMArg, CMArgs), CMArg == (::) ->
% the "::" meta-argument specifier is ambiguous in this context
throw(domain_error(meta_argument_specifier, Meta))
; ( '$lgt_prolog_phrase_predicate'(':'(Module, Pred)) ->
NewCaller = phrase
; NewCaller = meta
),
'$lgt_compile_prolog_meta_arguments'(Args, CMArgs, NewCaller, Ctx, TArgs, DArgs) ->
TPred0 =.. [Functor| TArgs],
TPred = ':'(Module, TPred0),
DPred0 =.. [Functor| DArgs],
DPred = '$lgt_debug'(goal(':'(Module, Pred), ':'(Module, DPred0)), ExCtx)
; throw(domain_error(meta_directive_template, Meta))
)
; % we're compiling a call to a module predicate
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_module_predicate'(Mode, Module, Pred, Pred, Head),
TPred = ':'(Module, Pred),
DPred = '$lgt_debug'(goal(':'(Module, Pred), TPred), ExCtx)
).
% reflection built-in predicates
'$lgt_compile_body'(current_op(Priority, Specifier, Operator), _, TPred, DPred, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
Entity == user,
% usually a call from an initialization or conditional compilation directive
!,
TPred = current_op(Priority, Specifier, Operator),
DPred = '$lgt_debug'(goal(current_op(Priority, Specifier, Operator), TPred), ExCtx).
'$lgt_compile_body'(current_op(Priority, Specifier, Operator), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_operator_priority, Priority),
'$lgt_check'(var_or_operator_specifier, Specifier),
'$lgt_check'(var_or_atom, Operator),
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
TPred = '$lgt_current_op'(Database, Priority, Specifier, Operator, Database, p(_), ExCtx),
DPred = '$lgt_debug'(goal(current_op(Priority, Specifier, Operator), TPred), ExCtx).
'$lgt_compile_body'(current_predicate(Term), _, TPred, DPred, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
Entity == user,
% usually a call from an initialization or conditional compilation directive
!,
TPred = current_predicate(Term),
DPred = '$lgt_debug'(goal(current_predicate(Term), TPred), ExCtx).
'$lgt_compile_body'(current_predicate(Term), Caller, TPred, DPred, Ctx) :-
nonvar(Term),
Term = ':'(Module, Pred),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Pred),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::current_predicate(Pred), Caller, TPred, DPred, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = current_predicate(':'(Module, Pred)),
DPred = '$lgt_debug'(goal(current_predicate(':'(Module, Pred)), TPred), ExCtx)
).
'$lgt_compile_body'(current_predicate(Term), Caller, TPred, DPred, Ctx) :-
'$lgt_valid_predicate_indicator'(Term, AliasFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
functor(Head, HeadFunctor, Arity),
'$lgt_compile_body'(Obj::current_predicate(HeadFunctor/Arity), Caller, TPred, DPred, Ctx)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
functor(Head, HeadFunctor, Arity),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = current_predicate(':'(Module, HeadFunctor/Arity)),
DPred = '$lgt_debug'(goal(current_predicate(':'(Module, HeadFunctor/Arity)), TPred), ExCtx)
; fail
),
!.
'$lgt_compile_body'(current_predicate(Pred), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_predicate_indicator, Pred),
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
TPred = '$lgt_current_predicate'(Database, Pred, Database, p(_), ExCtx),
DPred = '$lgt_debug'(goal(current_predicate(Pred), TPred), ExCtx).
'$lgt_compile_body'(predicate_property(Term, Prop), _, TPred, DPred, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
Entity == user,
% usually a call from an initialization or conditional compilation directive
!,
TPred = '$lgt_predicate_property'(Term, Prop),
DPred = '$lgt_debug'(goal(predicate_property(Term, Prop), TPred), ExCtx).
'$lgt_compile_body'(predicate_property(Term, Prop), Caller, TPred, DPred, Ctx) :-
nonvar(Term),
Term = ':'(Module, Head),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::predicate_property(Head, Prop), Caller, TPred, DPred, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = predicate_property(':'(Module, Head), Prop),
DPred = '$lgt_debug'(goal(predicate_property(':'(Module,Head), Prop), TPred), ExCtx)
).
'$lgt_compile_body'(predicate_property(Alias, Prop), Caller, TPred, DPred, Ctx) :-
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::predicate_property(Head, Prop), Caller, TPred, DPred, Ctx)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = predicate_property(':'(Module, Head), Prop),
DPred = '$lgt_debug'(goal(predicate_property(':'(Module,Head), Prop), TPred), ExCtx)
; fail
),
!.
'$lgt_compile_body'(predicate_property(Pred, Prop), _, TPred, DPred, Ctx) :-
!,
'$lgt_check'(var_or_callable, Pred),
'$lgt_check'(var_or_predicate_property, Prop),
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
TPred = '$lgt_predicate_property'(Database, Pred, Prop, Database, p(_), ExCtx),
DPred = '$lgt_debug'(goal(predicate_property(Pred, Prop), TPred), ExCtx).
% database handling built-in predicates
'$lgt_compile_body'(abolish(Functor, Arity), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(abolish(_, _)),
\+ '$lgt_pp_defines_predicate_'(abolish(_, _), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, abolish/2, abolish/1)
)
; true
),
'$lgt_compile_body'(abolish(Functor/Arity), Caller, TCond, DCond, Ctx).
'$lgt_compile_body'(abolish(Term), Caller, TCond, DCond, Ctx) :-
nonvar(Term),
Term = ':'(Module, Pred),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Pred),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::abolish(Pred), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = abolish(':'(Module, Pred)),
DCond = '$lgt_debug'(goal(abolish(':'(Module, Pred)), TCond), ExCtx),
( ground(Term) ->
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Pred), CallerHead)
; true
)
).
'$lgt_compile_body'(abolish(Pred), Caller, TCond, DCond, Ctx) :-
'$lgt_valid_predicate_indicator'(Pred, AliasFunctor, Arity),
functor(Alias, AliasFunctor, Arity),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
functor(Head, HeadFunctor, Arity),
'$lgt_compile_body'(Obj::abolish(HeadFunctor/Arity), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
'$lgt_remember_updated_predicate'(Mode, Obj::HeadFunctor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
functor(Head, HeadFunctor, Arity),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = abolish(':'(Module, HeadFunctor/Arity)),
DCond = '$lgt_debug'(goal(abolish(':'(Module, HeadFunctor/Arity)), TCond), ExCtx),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, HeadFunctor/Arity), CallerHead)
; % proceed to next clause
fail
),
!.
'$lgt_compile_body'(abolish(Pred), _, TCond, DCond, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, Head, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
'$lgt_check'(var_or_predicate_indicator, Pred),
'$lgt_check_dynamic_directive'(Mode, Pred),
( ground(Pred) ->
TCond = '$lgt_abolish_checked'(Database, Pred, Database, p(_), ExCtx),
'$lgt_remember_updated_predicate'(Mode, Pred, Head)
; % partially instantiated predicate indicator; runtime check required
TCond = '$lgt_abolish'(Database, Pred, Database, p(_), ExCtx)
),
DCond = '$lgt_debug'(goal(abolish(Pred), TCond), ExCtx).
'$lgt_compile_body'(assert(Clause), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(assert(_)),
\+ '$lgt_pp_defines_predicate_'(assert(_), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, assert/1, assertz/1)
)
; true
),
'$lgt_compile_body'(assertz(Clause), Caller, TCond, DCond, Ctx).
'$lgt_compile_body'(asserta(QClause), Caller, TCond, DCond, Ctx) :-
nonvar(QClause),
'$lgt_module_qualified_clause'(QClause, Module, Clause, Head, Body),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::asserta(Clause), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = asserta(QClause),
DCond = '$lgt_debug'(goal(asserta(QClause), TCond), ExCtx),
( ground(QClause) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(asserta(Clause), Caller, TCond, DCond, Ctx) :-
nonvar(Clause),
( Clause = (Alias :- Body) ->
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::asserta((Head :- Body)), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = asserta((':'(Module,Head) :- Body)),
DCond = '$lgt_debug'(goal(asserta((':'(Module,Head) :- Body)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
; Clause = Alias,
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::asserta(Head), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = asserta(':'(Module,Head)),
DCond = '$lgt_debug'(goal(asserta(':'(Module,Head)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
),
!.
'$lgt_compile_body'(asserta(Clause), _, TCond, DCond, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Clause, TClause) ->
TCond = asserta(TClause),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TCond = '$lgt_asserta'(Database, Clause, Database, p(_), p, ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TCond = '$lgt_asserta_fact_checked'(Database, Head, Database, p(_), p, ExCtx)
; TCond = '$lgt_asserta_rule_checked'(Database, Clause, Database, p(_), p, ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; TCond = '$lgt_asserta_fact_checked'(Database, Clause, Database, p(_), p, ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
)
),
'$lgt_check_dynamic_directive'(Mode, Clause)
),
DCond = '$lgt_debug'(goal(asserta(Clause), TCond), ExCtx).
'$lgt_compile_body'(assertz(QClause), Caller, TCond, DCond, Ctx) :-
nonvar(QClause),
'$lgt_module_qualified_clause'(QClause, Module, Clause, Head, Body),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::assertz(Clause), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = assertz(QClause),
DCond = '$lgt_debug'(goal(assertz(QClause), TCond), ExCtx),
( ground(QClause) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(assertz(Clause), Caller, TCond, DCond, Ctx) :-
nonvar(Clause),
( Clause = (Alias :- Body) ->
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::assertz((Head :- Body)), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = assertz((':'(Module,Head) :- Body)),
DCond = '$lgt_debug'(goal(assertz((':'(Module,Head) :- Body)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
; Clause = Alias,
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::assertz(Head), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = assertz(':'(Module,Head)),
DCond = '$lgt_debug'(goal(assertz(':'(Module,Head)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
),
!.
'$lgt_compile_body'(assertz(Clause), _, TCond, DCond, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Clause, TClause) ->
TCond = assertz(TClause),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TCond = '$lgt_assertz'(Database, Clause, Database, p(_), p, ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TCond = '$lgt_assertz_fact_checked'(Database, Head, Database, p(_), p, ExCtx)
; TCond = '$lgt_assertz_rule_checked'(Database, Clause, Database, p(_), p, ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; TCond = '$lgt_assertz_fact_checked'(Database, Clause, Database, p(_), p, ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
)
),
'$lgt_check_dynamic_directive'(Mode, Clause)
),
DCond = '$lgt_debug'(goal(assertz(Clause), TCond), ExCtx).
'$lgt_compile_body'(clause(QHead, Body), Caller, TCond, DCond, Ctx) :-
nonvar(QHead),
QHead = ':'(Module, Head),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::clause(Head, Body), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = clause(QHead, Body),
DCond = '$lgt_debug'(goal(clause(QHead, Body), TCond), ExCtx),
( ground(QHead) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(clause(Alias, Body), Caller, TCond, DCond, Ctx) :-
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::clause(Head, Body), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = clause(':'(Module,Head), Body),
DCond = '$lgt_debug'(goal(clause(':'(Module,Head), Body), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; fail
),
!.
'$lgt_compile_body'(clause(Head, Body), _, TCond, DCond, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Head, THead) ->
'$lgt_check'(var_or_callable, Body),
TCond = (clause(THead, TBody), (TBody = ('$lgt_nop'(Body), _) -> true; TBody = Body)),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'((Head :- Body)) ->
TCond = '$lgt_clause'(Database, Head, Body, Database, p(_), ExCtx)
; '$lgt_check'(clause, (Head :- Body)),
TCond = '$lgt_clause_checked'(Database, Head, Body, Database, p(_), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
),
'$lgt_check_dynamic_directive'(Mode, Head)
),
DCond = '$lgt_debug'(goal(clause(Head, Body), TCond), ExCtx).
'$lgt_compile_body'(retract(QClause), Caller, TCond, DCond, Ctx) :-
nonvar(QClause),
'$lgt_module_qualified_clause'(QClause, Module, Clause, Head, Body),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::retract(Clause), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = retract(QClause),
DCond = '$lgt_debug'(goal(retract(QClause), TCond), ExCtx),
( ground(QClause) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(retract(Clause), Caller, TCond, DCond, Ctx) :-
nonvar(Clause),
( Clause = (Alias :- Body) ->
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::retract((Head :- Body)), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = retract((':'(Module,Head) :- Body)),
DCond = '$lgt_debug'(goal(retract((':'(Module,Head) :- Body)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
; Clause = Alias,
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::retract(Head), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = retract(':'(Module,Head)),
DCond = '$lgt_debug'(goal(retract(':'(Module,Head)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
),
!.
'$lgt_compile_body'(retract(Clause), _, TCond, DCond, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Clause, TClause) ->
TCond = retract(TClause),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TCond = '$lgt_retract'(Database, Clause, Database, p(_), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( var(Body) ->
TCond = '$lgt_retract_var_body_checked'(Database, Clause, Database, p(_), ExCtx)
; Body == true ->
TCond = '$lgt_retract_fact_checked'(Database, Head, Database, p(_), ExCtx)
; TCond = '$lgt_retract_rule_checked'(Database, Clause, Database, p(_), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; TCond = '$lgt_retract_fact_checked'(Database, Clause, Database, p(_), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
)
),
'$lgt_check_dynamic_directive'(Mode, Clause)
),
DCond = '$lgt_debug'(goal(retract(Clause), TCond), ExCtx).
'$lgt_compile_body'(retractall(QHead), Caller, TCond, DCond, Ctx) :-
nonvar(QHead),
QHead = ':'(Module, Head),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::retractall(Head), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = retractall(QHead),
DCond = '$lgt_debug'(goal(retractall(QHead), TCond), ExCtx),
( ground(QHead) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(retractall(Alias), Caller, TCond, DCond, Ctx) :-
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::retractall(Head), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = retractall(':'(Module,Head)),
DCond = '$lgt_debug'(goal(retractall(':'(Module,Head)), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
),
!.
'$lgt_compile_body'(retractall(Head), _, TCond, DCond, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Head, THead) ->
TCond = retractall(THead),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( var(Head) ->
TCond = '$lgt_retractall'(Database, Head, Database, p(_), ExCtx)
; '$lgt_check'(callable, Head),
TCond = '$lgt_retractall_checked'(Database, Head, Database, p(_), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
),
'$lgt_check_dynamic_directive'(Mode, Head)
),
DCond = '$lgt_debug'(goal(retractall(Head), TCond), ExCtx).
% database handling built-in predicates that take a clause reference
% if supported as built-in predicates by the backend Prolog compiler
'$lgt_compile_body'(assert(Clause, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(assert(_, _)),
\+ '$lgt_pp_defines_predicate_'(assert(_, _), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, assert/2, assertz/2)
)
; true
),
'$lgt_compile_body'(assertz(Clause, Ref), Caller, TCond, DCond, Ctx).
'$lgt_compile_body'(asserta(QClause, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(asserta(_, _)),
\+ '$lgt_pp_defines_predicate_'(asserta(_, _), _, _, _, _, _),
nonvar(QClause),
'$lgt_module_qualified_clause'(QClause, Module, Clause, Head, Body),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::asserta(Clause, Ref), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = asserta(QClause, Ref),
DCond = '$lgt_debug'(goal(asserta(QClause, Ref), TCond), ExCtx),
( ground(QClause) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(asserta(Clause, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(asserta(_, _)),
\+ '$lgt_pp_defines_predicate_'(asserta(_, _), _, _, _, _, _),
nonvar(Clause),
( Clause = (Alias :- Body) ->
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::asserta((Head :- Body), Ref), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = asserta((':'(Module,Head) :- Body), Ref),
DCond = '$lgt_debug'(goal(asserta((':'(Module,Head) :- Body), Ref), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
; Clause = Alias,
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::asserta(Head, Ref), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = asserta(':'(Module,Head), Ref),
DCond = '$lgt_debug'(goal(asserta(':'(Module,Head), Ref), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
),
!.
'$lgt_compile_body'(asserta(Clause, Ref), _, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(asserta(_, _)),
\+ '$lgt_pp_defines_predicate_'(asserta(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Clause, TClause) ->
TCond = asserta(TClause, Ref),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TCond = '$lgt_asserta'(Database, Clause, Ref, Database, p(_), p)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TCond = '$lgt_asserta_fact_checked'(Database, Head, Ref, Database, p(_), p, ExCtx)
; TCond = '$lgt_asserta_rule_checked'(Database, Clause, Ref, Database, p(_), p, ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; TCond = '$lgt_asserta_fact_checked'(Database, Clause, Ref, Database, p(_), p, ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
)
),
'$lgt_check_dynamic_directive'(Mode, Clause)
),
DCond = '$lgt_debug'(goal(asserta(Clause, Ref), TCond), ExCtx).
'$lgt_compile_body'(assertz(QClause, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(assertz(_, _)),
\+ '$lgt_pp_defines_predicate_'(assertz(_, _), _, _, _, _, _),
nonvar(QClause),
'$lgt_module_qualified_clause'(QClause, Module, Clause, Head, Body),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::assertz(Clause, Ref), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = assertz(QClause),
DCond = '$lgt_debug'(goal(assertz(QClause, Ref), TCond), ExCtx),
( ground(QClause) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(assertz(Clause, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(assertz(_, _)),
\+ '$lgt_pp_defines_predicate_'(assertz(_, _), _, _, _, _, _),
nonvar(Clause),
( Clause = (Alias :- Body) ->
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::assertz((Head :- Body), Ref), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = assertz((':'(Module,Head) :- Body), Ref),
DCond = '$lgt_debug'(goal(assertz((':'(Module,Head) :- Body), Ref), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
; Clause = Alias,
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::assertz(Head, Ref), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = assertz(':'(Module,Head), Ref),
DCond = '$lgt_debug'(goal(assertz(':'(Module,Head), Ref), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; % proceed to next clause
fail
)
),
!.
'$lgt_compile_body'(assertz(Clause, Ref), _, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(assertz(_, _)),
\+ '$lgt_pp_defines_predicate_'(assertz(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Clause, TClause) ->
TCond = assertz(TClause, Ref),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TCond = '$lgt_assertz'(Database, Clause, Ref, Database, p(_), p, ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TCond = '$lgt_assertz_fact_checked'(Database, Head, Ref, Database, p(_), p, ExCtx)
; TCond = '$lgt_assertz_rule_checked'(Database, Clause, Ref, Database, p(_), p, ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; TCond = '$lgt_assertz_fact_checked'(Database, Clause, Ref, Database, p(_), p, ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
)
),
'$lgt_check_dynamic_directive'(Mode, Clause)
),
DCond = '$lgt_debug'(goal(assertz(Clause, Ref), TCond), ExCtx).
'$lgt_compile_body'(clause(QHead, Body, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(clause(_, _, _)),
\+ '$lgt_pp_defines_predicate_'(clause(_, _, _), _, _, _, _, _),
nonvar(QHead),
QHead = ':'(Module, Head),
!,
'$lgt_check'(var_or_module_identifier, Module),
'$lgt_check'(var_or_callable, Head),
'$lgt_check'(var_or_callable, Body),
( '$lgt_pp_module_'(_) ->
% we're compiling a module as an object; assume referenced modules are also compiled as objects
'$lgt_compile_body'(Module::clause(Head, Body, Ref), Caller, TCond, DCond, Ctx)
; % we're using modules together with objects
'$lgt_add_referenced_module'(Module, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = clause(QHead, Body, Ref),
DCond = '$lgt_debug'(goal(clause(QHead, Body, Ref), TCond), ExCtx),
( ground(QHead) ->
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; true
)
).
'$lgt_compile_body'(clause(Alias, Body, Ref), Caller, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(clause(_, _, _)),
\+ '$lgt_pp_defines_predicate_'(clause(_, _, _), _, _, _, _, _),
nonvar(Alias),
( '$lgt_pp_uses_predicate_'(Obj, Head, Alias, Ctx, _, _) ->
'$lgt_compile_body'(Obj::clause(Head, Body, Ref), Caller, TCond, DCond, Ctx),
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; '$lgt_pp_use_module_predicate_'(Module, Head, Alias, Ctx, _, _) ->
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TCond = clause(':'(Module,Head), Body, Ref),
DCond = '$lgt_debug'(goal(clause(':'(Module,Head), Body), TCond), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ':'(Module, Functor/Arity), CallerHead)
; fail
),
!.
'$lgt_compile_body'(clause(Head, Body, Ref), _, TCond, DCond, Ctx) :-
'$lgt_prolog_built_in_predicate'(clause(_, _, _)),
\+ '$lgt_pp_defines_predicate_'(clause(_, _, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, Entity, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_optimizable_local_db_call'(Head, THead) ->
'$lgt_check'(var_or_callable, Body),
TCond = (clause(THead, TBody, Ref), (TBody = ('$lgt_nop'(Body), _) -> true; TBody = Body)),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
; '$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx),
( '$lgt_runtime_checked_db_clause'((Head :- Body)) ->
TCond = '$lgt_clause'(Database, Head, Body, Ref, Database, p(_), ExCtx)
; '$lgt_check'(clause, (Head :- Body)),
TCond = '$lgt_clause_checked'(Database, Head, Body, Ref, Database, p(_), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Functor/Arity, CallerHead)
),
'$lgt_check_dynamic_directive'(Mode, Head)
),
DCond = '$lgt_debug'(goal(clause(Head, Body, Ref), TCond), ExCtx).
'$lgt_compile_body'(erase(Ref), _, erase(Ref), '$lgt_debug'(goal(erase(Ref), erase(Ref)), ExCtx), Ctx) :-
'$lgt_prolog_built_in_predicate'(erase(_)),
\+ '$lgt_pp_defines_predicate_'(erase(_), _, _, _, _, _),
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
% term and goal expansion predicates
'$lgt_compile_body'(expand_term(Term, Expansion), _, TPred, '$lgt_debug'(goal(expand_term(Term, Expansion), TPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
TPred = '$lgt_expand_term_local'(Entity, Term, Expansion, ExCtx).
'$lgt_compile_body'(expand_goal(Goal, ExpandedGoal), _, TPred, '$lgt_debug'(goal(expand_goal(Goal, ExpandedGoal), TPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
TPred = '$lgt_expand_goal_local'(Entity, Goal, ExpandedGoal, ExCtx).
% DCG predicates
%
% defer to runtime compilation of variable grammar rule
% body arguments to prevent a compilation endless loop
'$lgt_compile_body'(phrase(GRBody, Input), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, MetaVars, _, ExCtx, _, _, _, _),
( '$lgt_member_var'(GRBody, MetaVars) ->
TPred = '$lgt_phrase'(GRBody, Input, HeadExCtx, runtime)
; TPred = '$lgt_phrase'(GRBody, Input, HeadExCtx, local)
).
'$lgt_compile_body'(phrase(::GRBody, Input), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
TPred = '$lgt_phrase'(::GRBody, Input, HeadExCtx, local).
'$lgt_compile_body'(phrase(Obj::GRBody, Input), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
TPred = '$lgt_phrase'(Obj::GRBody, Input, HeadExCtx, local).
'$lgt_compile_body'(phrase(^^GRBody, Input), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
TPred = '$lgt_phrase'(^^GRBody, Input, HeadExCtx, local).
'$lgt_compile_body'(phrase(Obj<
TPred = '$lgt_phrase'(GRBody, Input, Rest, HeadExCtx, runtime)
; TPred = '$lgt_phrase'(GRBody, Input, Rest, HeadExCtx, local)
).
'$lgt_compile_body'(phrase(::GRBody, Input, Rest), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input, Rest), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_check'(list_or_partial_list, Rest),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
TPred = '$lgt_phrase'(::GRBody, Input, Rest, HeadExCtx, local).
'$lgt_compile_body'(phrase(Obj::GRBody, Input, Rest), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input, Rest), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_check'(list_or_partial_list, Rest),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
TPred = '$lgt_phrase'(Obj::GRBody, Input, Rest, HeadExCtx, local).
'$lgt_compile_body'(phrase(^^GRBody, Input, Rest), _, TPred, '$lgt_debug'(goal(phrase(GRBody, Input, Rest), TPred), ExCtx), Ctx) :-
var(GRBody),
!,
'$lgt_check'(list_or_partial_list, Input),
'$lgt_check'(list_or_partial_list, Rest),
'$lgt_comp_ctx'(Ctx, _, HeadExCtx, _, _, _, _, _, _, _, ExCtx, _, _, _, _),
TPred = '$lgt_phrase'(^^GRBody, Input, Rest, HeadExCtx, local).
'$lgt_compile_body'(phrase(Obj<
throw(representation_error(acyclic_term))
; Head0 = _::Head ->
% multifile predicate
true
; Head0 = ':'(_,Head) ->
% assume Prolog module multifile predicate
true
; Head0 = Head
),
'$lgt_comp_ctx_head_exec_ctx'(Ctx, ExCtx),
Context = logtalk(Head, ExCtx).
'$lgt_compile_body'(sender(Sender), _, TPred, '$lgt_debug'(goal(sender(DSender), DPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_head_exec_ctx'(Ctx, ExCtx),
'$lgt_execution_context'(ExCtx, _, Sender0, _, _, _, _),
( var(Sender) ->
% compile time unification
Sender0 = Sender,
TPred = true,
DPred = (DSender = Sender)
; % we must delay unification to runtime
TPred = (Sender0 = Sender),
DPred = TPred,
DSender = Sender
).
'$lgt_compile_body'(this(This), _, TPred, '$lgt_debug'(goal(this(DThis), DPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_head_exec_ctx'(Ctx, ExCtx),
'$lgt_execution_context_this_entity'(ExCtx, This0, _),
( var(This) ->
% compile time unification
This0 = This,
TPred = true,
DPred = (DThis = This)
; % we must delay unification to runtime
TPred = (This0 = This),
DPred = TPred,
DThis = This
).
'$lgt_compile_body'(self(Self), _, TPred, '$lgt_debug'(goal(self(DSelf), DPred), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx_head_exec_ctx'(Ctx, ExCtx),
'$lgt_execution_context'(ExCtx, _, _, _, Self0, _, _),
( var(Self) ->
% compile time unification
Self0 = Self,
TPred = true,
DPred = (DSelf = Self)
; % we must delay unification to runtime
TPred = (Self0 = Self),
DPred = TPred,
DSelf = Self
).
'$lgt_compile_body'(parameter(Arg, _), _, _, _, Ctx) :-
'$lgt_check'(integer, Arg),
( '$lgt_pp_entity_'(_, Entity, _) ->
% compile time
true
; % runtime <2 call
'$lgt_comp_ctx_entity'(Ctx, Entity)
),
\+ compound(Entity),
throw(type_error(parametric_entity, Entity)).
'$lgt_compile_body'(parameter(Arg, Value), _, TPred, '$lgt_debug'(goal(parameter(Arg, DValue), DPred), ExCtx), Ctx) :-
!,
( '$lgt_pp_entity_'(_, Entity, _) ->
% compile time; instantiate the Entity argument in the compilation context
true
; % runtime <2 call; Entity alreay instantiated in the compilation context
true
),
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
functor(Entity, _, Arity),
( 1 =< Arg, Arg =< Arity ->
arg(Arg, Entity, Value0),
( var(Value) ->
% parameter compile time unification
Value0 = Value,
TPred = true,
DPred = (DValue = Value)
; % we must delay unification to runtime
TPred = (Value0 = Value),
DPred = TPred,
DValue = Value
)
; throw(domain_error([1,Arity], Arg))
).
% open/4 portability lint warnings only
'$lgt_compile_body'(open(_, _, _, Options), _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, Mode),
'$lgt_check_open_stream_options'(Mode, open/4, Options),
fail.
% term input predicates that need to be operator aware
% (these translations are only applied if there are local entity operators declared)
'$lgt_compile_body'(read_term(Stream, Term, Options), _, '$lgt_iso_read_term'(Stream, Term, Options, Ops), '$lgt_debug'(goal(read_term(Stream, Term, Options), '$lgt_iso_read_term'(Stream, Term, Options, Ops)), ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_check_read_term_options'(Mode, read_term/3, Options),
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
!.
'$lgt_compile_body'(read_term(Term, Options), _, '$lgt_iso_read_term'(Term, Options, Ops), '$lgt_debug'(goal(read_term(Term, Options), '$lgt_iso_read_term'(Term, Options, Ops)), ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_check_read_term_options'(Mode, read_term/2, Options),
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
!.
'$lgt_compile_body'(read(Stream, Term), _, '$lgt_iso_read'(Stream, Term, Ops), '$lgt_debug'(goal(read(Stream, Term), '$lgt_iso_read'(Stream, Term, Ops)), ExCtx), Ctx) :-
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
!.
'$lgt_compile_body'(read(Term), _, '$lgt_iso_read'(Term, Ops), '$lgt_debug'(goal(read(Term), '$lgt_iso_read'(Term, Ops)), ExCtx), Ctx) :-
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
!.
% term output predicates that need to be operator aware
% (these translations are only applied if there are local entity operators declared)
'$lgt_compile_body'(write_term(Stream, Term, Options), _, '$lgt_iso_write_term'(Stream, Term, Options, Ops), '$lgt_debug'(goal(write_term(Stream, Term, Options), '$lgt_iso_write_term'(Stream, Term, Options, Ops)), ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_check_write_term_options'(Mode, write_term/3, Options),
('$lgt_member'(ignore_ops(Value), Options) -> Value \== true; true),
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
!.
'$lgt_compile_body'(write_term(Term, Options), _, '$lgt_iso_write_term'(Term, Options, Ops), '$lgt_debug'(goal(write_term(Term, Options), '$lgt_iso_write_term'(Term, Options, Ops)), ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_check_write_term_options'(Mode, write_term/2, Options),
('$lgt_member'(ignore_ops(Value), Options) -> Value \== true; true),
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
!.
'$lgt_compile_body'(write(Stream, Term), _, '$lgt_iso_write'(Stream, Term, Ops), '$lgt_debug'(goal(write(Stream, Term), '$lgt_iso_write'(Stream, Term, Ops)), ExCtx), Ctx) :-
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
!.
'$lgt_compile_body'(write(Term), _, '$lgt_iso_write'(Term, Ops), '$lgt_debug'(goal(write(Term), '$lgt_iso_write'(Term, Ops)), ExCtx), Ctx) :-
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
!.
'$lgt_compile_body'(writeq(Stream, Term), _, '$lgt_iso_writeq'(Stream, Term, Ops), '$lgt_debug'(goal(writeq(Stream, Term), '$lgt_iso_writeq'(Stream, Term, Ops)), ExCtx), Ctx) :-
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
!.
'$lgt_compile_body'(writeq(Term), _, '$lgt_iso_writeq'(Term, Ops), '$lgt_debug'(goal(writeq(Term), '$lgt_iso_writeq'(Term, Ops)), ExCtx), Ctx) :-
bagof(op(Pr, Spec, Op), Scope^File^Lines^'$lgt_pp_entity_operator_'(Pr, Spec, Op, Scope, File, Lines), Ops),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
!.
% Logtalk flag predicates
'$lgt_compile_body'(set_logtalk_flag(Flag, Value), _, TPred, '$lgt_debug'(goal(DPred, TPred), ExCtx), Ctx) :-
nonvar(Flag),
nonvar(Value),
!,
'$lgt_check'(read_write_flag, Flag),
'$lgt_check'(flag_value, Flag + Value),
TPred = '$lgt_set_compiler_flag'(Flag, Value),
DPred = set_logtalk_flag(Flag, Value),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(set_logtalk_flag(Flag, Value), _, TPred, '$lgt_debug'(goal(DPred, TPred), ExCtx), Ctx) :-
!,
'$lgt_check'(var_or_read_write_flag, Flag),
TPred = '$lgt_set_logtalk_flag'(Flag, Value, ExCtx),
DPred = set_logtalk_flag(Flag, Value),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(current_logtalk_flag(Flag, Value), _, TPred, '$lgt_debug'(goal(DPred, TPred), ExCtx), Ctx) :-
nonvar(Flag),
nonvar(Value),
!,
'$lgt_check'(flag, Flag),
'$lgt_check'(flag_value, Flag + Value),
TPred = '$lgt_compiler_flag'(Flag, Value),
DPred = current_logtalk_flag(Flag, Value),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(current_logtalk_flag(Flag, Value), _, TPred, '$lgt_debug'(goal(DPred, TPred), ExCtx), Ctx) :-
!,
'$lgt_check'(var_or_flag, Flag),
TPred = '$lgt_current_logtalk_flag'(Flag, Value, ExCtx),
DPred = current_logtalk_flag(Flag, Value),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_body'(create_logtalk_flag(Flag, Value, Options), _, TPred, '$lgt_debug'(goal(DPred, TPred), ExCtx), Ctx) :-
!,
'$lgt_check'(atom, Flag),
'$lgt_check'(ground, Value),
'$lgt_check'(ground, Options),
'$lgt_check'(list, Options),
TPred = '$lgt_create_logtalk_flag'(Flag, Value, Options, ExCtx),
DPred = create_logtalk_flag(Flag, Value, Options),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
% Prolog flag predicates (just basic error and portability checking)
'$lgt_compile_body'(set_prolog_flag(Flag, _), _, _, _, Ctx) :-
'$lgt_check'(var_or_atom, Flag),
nonvar(Flag),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning),
\+ '$lgt_iso_spec_flag'(Flag),
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(warning(portability), non_standard_prolog_flag(File, Lines, Type, Entity, Flag))
; '$lgt_print_message'(warning(portability), non_standard_prolog_flag(File, Lines, Flag))
),
fail.
'$lgt_compile_body'(set_prolog_flag(Flag, Value), _, _, _, Ctx) :-
nonvar(Flag),
nonvar(Value),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_iso_spec_flag'(Flag),
\+ '$lgt_iso_spec_flag_value'(Flag, Value),
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(warning(portability), non_standard_prolog_flag_value(File, Lines, Type, Entity, Flag, Value))
; '$lgt_print_message'(warning(portability), non_standard_prolog_flag_value(File, Lines, Flag, Value))
),
fail.
'$lgt_compile_body'(current_prolog_flag(Flag, _), _, _, _, Ctx) :-
'$lgt_check'(var_or_atom, Flag),
nonvar(Flag),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning),
\+ '$lgt_iso_spec_flag'(Flag),
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(warning(portability), non_standard_prolog_flag(File, Lines, Type, Entity, Flag))
; '$lgt_print_message'(warning(portability), non_standard_prolog_flag(File, Lines, Flag))
),
fail.
'$lgt_compile_body'(current_prolog_flag(Flag, Value), _, _, _, Ctx) :-
nonvar(Flag),
nonvar(Value),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_iso_spec_flag'(Flag),
\+ '$lgt_iso_spec_flag_value'(Flag, Value),
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_print_message'(warning(portability), non_standard_prolog_flag_value(File, Lines, Type, Entity, Flag, Value))
; '$lgt_print_message'(warning(portability), non_standard_prolog_flag_value(File, Lines, Flag, Value))
),
fail.
% arithmetic predicates (portability and trivial fail checks)
'$lgt_compile_body'(Term is Exp, _, _, _, _) :-
nonvar(Term),
once((
integer(Term),
'$lgt_float_expression'(Exp)
% integers and floats do not unify (per standard)
; float(Term),
'$lgt_integer_expression'(Exp)
% integers and floats do not unify (per standard)
; \+ number(Term)
% the standard allows any term in the left side
)),
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(always_true_or_false_goals), goal_is_always_false(File, Lines, Type, Entity, Term is Exp)),
fail.
'$lgt_compile_body'(Term is Exp, _, _, _, _) :-
var(Term),
Term \== Exp,
term_variables(Exp, ExpVariables),
once('$lgt_member_var'(Term, ExpVariables)),
% this could also be a "goal is always false" warning
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Term is Exp, reason(shared_variable(Term)))
),
fail.
'$lgt_compile_body'(_ is Exp, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp, Ctx),
fail.
'$lgt_compile_body'(Exp1 =:= Exp2, _, _, _, Ctx) :-
once((
'$lgt_float_expression'(Exp1)
; '$lgt_float_expression'(Exp2)
)),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(arithmetic_expressions),
suspicious_call(File, Lines, Type, Entity, Exp1 =:= Exp2, reason(float_comparison))
),
fail.
'$lgt_compile_body'(Exp1 =:= Exp2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp1, Ctx),
'$lgt_check_non_portable_functions'(Exp2, Ctx),
fail.
'$lgt_compile_body'(Exp1 =\= Exp2, _, _, _, Ctx) :-
once((float(Exp1); float(Exp2))),
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(arithmetic_expressions),
suspicious_call(File, Lines, Type, Entity, Exp1 =\= Exp2, reason(float_comparison))
),
fail.
'$lgt_compile_body'(Exp1 =\= Exp2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp1, Ctx),
'$lgt_check_non_portable_functions'(Exp2, Ctx),
fail.
'$lgt_compile_body'(Exp1 < Exp2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp1, Ctx),
'$lgt_check_non_portable_functions'(Exp2, Ctx),
fail.
'$lgt_compile_body'(Exp1 =< Exp2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp1, Ctx),
'$lgt_check_non_portable_functions'(Exp2, Ctx),
fail.
'$lgt_compile_body'(Exp1 > Exp2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp1, Ctx),
'$lgt_check_non_portable_functions'(Exp2, Ctx),
fail.
'$lgt_compile_body'(Exp1 >= Exp2, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)),
'$lgt_compiler_flag'(portability, warning),
'$lgt_check_non_portable_functions'(Exp1, Ctx),
'$lgt_check_non_portable_functions'(Exp2, Ctx),
fail.
% blackboard predicates (requires a backend Prolog compiler natively supporting these built-in predicates)
'$lgt_compile_body'(bb_put(Key, Term), _, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(bb_put(_, _)),
\+ '$lgt_pp_defines_predicate_'(bb_put(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, _, _),
( atomic(Key) ->
'$lgt_compile_bb_key'(Key, Prefix, TKey),
TPred = bb_put(TKey, Term),
DPred = '$lgt_debug'(goal(bb_put(Key, Term), TPred), ExCtx)
; var(Key) ->
% runtime key translation
TPred = ('$lgt_compile_bb_key'(Key, Prefix, TKey, bb_put(Key, Term)), bb_put(TKey, Term)),
DPred = '$lgt_debug'(goal(bb_put(Key, Term), TPred), ExCtx)
; throw(type_error(atomic, Key))
).
'$lgt_compile_body'(bb_get(Key, Term), _, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(bb_get(_, _)),
\+ '$lgt_pp_defines_predicate_'(bb_get(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, _, _),
( atomic(Key) ->
'$lgt_compile_bb_key'(Key, Prefix, TKey),
TPred = bb_get(TKey, Term),
DPred = '$lgt_debug'(goal(bb_get(Key, Term), TPred), ExCtx)
; var(Key) ->
% runtime key translation
TPred = ('$lgt_compile_bb_key'(Key, Prefix, TKey, bb_get(Key, Term)), bb_get(TKey, Term)),
DPred = '$lgt_debug'(goal(bb_get(Key, Term), TPred), ExCtx)
; throw(type_error(atomic, Key))
).
'$lgt_compile_body'(bb_delete(Key, Term), _, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(bb_delete(_, _)),
\+ '$lgt_pp_defines_predicate_'(bb_delete(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, _, _),
( atomic(Key) ->
'$lgt_compile_bb_key'(Key, Prefix, TKey),
TPred = bb_delete(TKey, Term),
DPred = '$lgt_debug'(goal(bb_delete(Key, Term), TPred), ExCtx)
; var(Key) ->
% runtime key translation
TPred = ('$lgt_compile_bb_key'(Key, Prefix, TKey, bb_delete(Key, Term)), bb_delete(TKey, Term)),
DPred = '$lgt_debug'(goal(bb_delete(Key, Term), TPred), ExCtx)
; throw(type_error(atomic, Key))
).
'$lgt_compile_body'(bb_update(Key, Term, New), _, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(bb_update(_, _, _)),
\+ '$lgt_pp_defines_predicate_'(bb_update(_, _, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, _, _, _, _),
( atomic(Key) ->
'$lgt_compile_bb_key'(Key, Prefix, TKey),
TPred = bb_update(TKey, Term, New),
DPred = '$lgt_debug'(goal(bb_update(Key, Term, New), TPred), ExCtx)
; var(Key) ->
% runtime key translation
TPred = ('$lgt_compile_bb_key'(Key, Prefix, TKey, bb_update(Key, Term, New)), bb_update(TKey, Term, New)),
DPred = '$lgt_debug'(goal(bb_update(Key, Term, New), TPred), ExCtx)
; throw(type_error(atomic, Key))
).
% call/2-N built-in control construct
'$lgt_compile_body'(CallN, Caller, TPred, DPred, Ctx) :-
functor(CallN, call, Arity),
Arity >= 2,
CallN =.. [call, Closure| ExtraArgs],
!,
( callable(Closure),
\+ '$lgt_logtalk_control_construct'(Closure),
Closure \= ':'(_, _),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtraArgs, FullArgs),
Goal =.. [Functor| FullArgs],
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, CallN, [Goal])
)
; true
),
'$lgt_check_closure'(Closure, Ctx),
'$lgt_compile_body'('$lgt_callN'(Closure, ExtraArgs), Caller, TPred, DPred, Ctx).
% call to a meta-predicate from a user-defined meta-predicate;
% must check the number of arguments for shared closures
%
% note that getting the meta-predicate template for non-declared
% built-in meta-predicates or for module meta-predicates is fragile
% due to lack of standardization of meta-predicate specifications
'$lgt_compile_body'(Pred, _, _, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, [_| _], _, _, compile(_,_,_), _, _, _),
% we're compiling a clause for a meta-predicate as the list of meta-variables is not empty
functor(Pred, Name, Arity),
\+ functor(Head, Name, Arity),
% not a recursive call
( '$lgt_pp_meta_predicate_'(Pred, Meta, _, _) ->
% local user-defined meta-predicate
true
; '$lgt_prolog_meta_predicate'(Pred, Meta, predicate) ->
% proprietary built-in meta-predicate declared in the adapter files
true
; '$lgt_predicate_property'(Pred, built_in),
catch('$lgt_predicate_property'(Pred, meta_predicate(Meta)), _, fail) ->
% non-declared proprietary built-in meta-predicate
true
; '$lgt_pp_use_module_predicate_'(Module, Original, Pred, _, _, _),
nonvar(Module),
catch('$lgt_predicate_property'(':'(Module, Original), meta_predicate(Meta)), _, fail) ->
% meta-predicates specified in a use_module/2 directive
true
; '$lgt_pp_uses_predicate_'(Obj, Original, Pred, _, _, _),
Obj == user,
catch('$lgt_predicate_property'(Original, meta_predicate(Meta)), _, fail) ->
% Prolog meta-predicate undeclared in the adapter file (may not be a built-in)
true
; fail
),
Pred =.. [_| PredArgs],
Meta =.. [_| MetaArgs],
'$lgt_prolog_to_logtalk_meta_argument_specifiers'(MetaArgs, CMetaArgs),
nonvar(Head),
% ignore multifile predicates
Head \= ':'(_, _),
Head \= _::_,
'$lgt_pp_meta_predicate_'(Head, HeadMeta, _, _),
Head =.. [_| HeadArgs],
HeadMeta =.. [_| HeadMetaArgs],
'$lgt_same_number_of_closure_extra_args'(PredArgs, CMetaArgs, HeadArgs, HeadMetaArgs, HeadMeta, Meta),
fail.
% predicates specified in use_module/2 directives
'$lgt_compile_body'(Alias, Caller, TPred, '$lgt_debug'(goal(Alias, TPred), ExCtx), Ctx) :-
'$lgt_pp_use_module_predicate_'(Module, Pred, Alias, Ctx, _, _),
( Pred == Alias ->
% no alias is defined
true
; % check that we're renaming a predicate but not (also) changing its argument order as that
% would break using the closure as a meta-argument when appending the additional arguments
Pred =.. [_| PredArguments],
Alias =.. [_| AliasArguments],
PredArguments == AliasArguments ->
true
; % we're renaming a predicate; use instead the generated auxiliary predicate
fail
),
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_module_predicate'(Mode, Module, Pred, Alias, Head),
'$lgt_compile_body'(':'(Module,Pred), Caller, TPred, _, Ctx).
% predicates specified in uses/2 directives
%
% in the case of predicates defined in the pseudo-object "user", the uses/2
% directive is typically used to help document dependencies on Prolog-defined
% predicates (usually, but not necessarily, built-in predicates)
'$lgt_compile_body'(Alias, Caller, TPred, DPred, Ctx) :-
'$lgt_pp_uses_predicate_'(Obj, Pred, Alias, Ctx, _, _),
( Pred == Alias ->
% no alias is defined
true
; % check that we're renaming a predicate but not (also) changing its argument order as that
% would break using the closure as a meta-argument when appending the additional arguments
Pred =.. [_| PredArguments],
Alias =.. [_| AliasArguments],
PredArguments == AliasArguments ->
true
; % we're renaming a predicate; use instead the generated auxiliary predicate
fail
),
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
( Obj == user ->
( ( '$lgt_prolog_meta_predicate'(Pred, Meta, Type)
% built-in Prolog meta-predicate declared in the adapter file in use
; catch('$lgt_predicate_property'(Pred, meta_predicate(Meta)), _, fail)
% Prolog meta-predicate undeclared in the adapter file (may not be a built-in)
; '$lgt_pp_meta_predicate_'(user::Pred, user::Meta, _, _)
% we're either providing a meta-predicate template or overriding the original
% meta-predicate template
) ->
% meta-predicate
Pred =.. [Functor| Args],
Meta =.. [Functor| MArgs],
( '$lgt_prolog_to_logtalk_meta_argument_specifiers'(MArgs, CMArgs),
'$lgt_compile_prolog_meta_arguments'(Args, CMArgs, meta, Ctx, TArgs, DArgs) ->
TPred =.. [Functor| TArgs],
DGoal =.. [Functor| DArgs],
( Type == control_construct ->
DPred = DGoal
; DPred = '$lgt_debug'(goal(Alias, DGoal), ExCtx)
)
; % meta-predicate template is not usable
throw(domain_error(meta_predicate_template, Meta))
)
; % non meta-predicate
TPred = Pred,
DPred = '$lgt_debug'(goal(Alias, Pred), ExCtx),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx)
),
'$lgt_add_referenced_object_message'(Mode, Obj, Pred, Alias, Head)
; % objects other than the pseudo-object "user"
'$lgt_add_referenced_object_message'(Mode, Obj, Pred, Alias, Head),
'$lgt_compile_body'(Obj::Pred, Caller, TPred, _, Ctx),
DPred = '$lgt_debug'(goal(Alias, TPred), ExCtx)
).
% call to a dynamic predicate from within a category; the predicate
% is called instead in the context of the object importing the category
% that received the message under processing (implicit dynamic binding)
'$lgt_compile_body'(Pred, _, TPred, '$lgt_debug'(goal(Pred, TPred), ExCtx), Ctx) :-
'$lgt_pp_category_'(_, _, _, _, _, _),
'$lgt_pp_dynamic_'(Pred, _, _, _),
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( functor(Pred, Functor, Arity),
\+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _) ->
% no scope directive
TPred = '$lgt_call_in_this'(Pred, ExCtx)
; TPred = '$lgt_call_in_this_checked'(Pred, ExCtx)
).
% non-callable terms
'$lgt_compile_body'(Pred, _, _, _, _) :-
\+ callable(Pred),
throw(type_error(callable, Pred)).
% runtime compilation of a call (usually a meta-call) to a user-defined predicate
%
% required to deal with meta-calls instantiated at runtime
'$lgt_compile_body'(Pred, _, TPred, '$lgt_debug'(goal(Pred, TPred), ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, Sender, This, Self, _, MetaVars, MetaCallCtx, ExCtx, runtime, Stack, _, _),
nonvar(Entity),
% in the most common case, we're meta-calling the predicate
'$lgt_execution_context'(ExCtx, Entity, Sender, This, Self, MetaCallCtx, Stack),
( '$lgt_member_var'(Pred, MetaVars) ->
% goal is a call to a user-defined predicate in sender (i.e. a meta-argument)
TPred = '$lgt_metacall_sender'(Pred, ExCtx, MetaCallCtx, [])
; % goal is a local call to a user-defined predicate
'$lgt_current_object_'(Entity, _, _, Def, _, _, _, _, DDef, _, _) ->
( call(Def, Pred, ExCtx, TPred)
; call(DDef, Pred, ExCtx, TPred)
)
; '$lgt_current_category_'(Entity, _, _, Def, _, _),
call(Def, Pred, ExCtx, TPred)
),
!.
% call to a local user-defined predicate
'$lgt_compile_body'(Pred, Caller, _, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, compile(user,_,_), _, Lines, Term),
Caller \== phrase,
Term \= (_ --> _),
functor(Pred, Functor, ExtArity),
'$lgt_pp_defines_non_terminal_'(Functor, Arity, ExtArity),
\+ '$lgt_pp_calls_non_terminal_'(Functor, Arity, ExtArity, Lines),
'$lgt_compiler_flag'(grammar_rules, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(grammar_rules),
calls_non_terminal_as_predicate(File, Lines, Type, Entity, Functor//Arity)
),
fail.
'$lgt_compile_body'(Pred, _, TPred, DPred, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
Entity == user,
% usually a call from an initialization or conditional compilation directive
!,
TPred = Pred,
DPred = '$lgt_debug'(goal(Pred, TPred), ExCtx).
'$lgt_compile_body'(Pred, _, TPred, '$lgt_debug'(goal(DPred, TPred), ExCtx), Ctx) :-
'$lgt_pp_coinductive_'(Pred, _, ExCtx, TCPred, _, _, DCPred, _, _),
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, Lines, _),
( '$lgt_pp_defines_predicate_'(Pred, Functor/Arity, _, TPred0, _, _) ->
'$lgt_check_for_trivial_fails'(Mode, Pred, TPred0, Head),
% convert the call to the original coinductive predicate into a call to the auxiliary
% predicate whose compiled normal and debug forms are already computed
functor(TCPred, TCFunctor, TCArity),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TCFunctor/TCArity, Head),
TPred = TCPred,
DPred = DCPred
; % undefined coinductive predicate
functor(Pred, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TFunctor/TArity, Head),
% closed-world assumption: calls to static, declared but undefined
% predicates must fail instead of throwing an exception,
'$lgt_report_undefined_predicate_call'(Mode, Functor/Arity, Lines),
TPred = fail,
DPred = Pred
).
'$lgt_compile_body'(Pred, _, TPred, '$lgt_debug'(goal(Pred, TPred), ExCtx), Ctx) :-
'$lgt_pp_synchronized_'(Pred, Mutex, _, _),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, Lines, _),
functor(Pred, Functor, Arity),
\+ (nonvar(Head), functor(Head, Functor, Arity)),
% not a recursive call
!,
( '$lgt_pp_defines_predicate_'(Pred, _, ExCtx, TPred0, _, _) ->
'$lgt_check_for_trivial_fails'(Mode, Pred, TPred0, Head),
( '$lgt_prolog_feature'(threads, supported) ->
TPred = with_mutex(Mutex, TPred0)
; % in single-threaded systems, with_mutex/2 is equivalent to once/1
TPred = once(TPred0)
),
functor(TPred0, TFunctor, TArity)
; % undefined synchronized predicate
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
% closed-world assumption: calls to static, declared but undefined
% predicates must fail instead of throwing an exception,
'$lgt_report_undefined_predicate_call'(Mode, Functor/Arity, Lines),
TPred = fail
),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TFunctor/TArity, Head).
'$lgt_compile_body'(Pred, Caller, TPred, '$lgt_debug'(goal(Pred, TPred), ExCtx), Ctx) :-
'$lgt_pp_defines_predicate_'(Pred, Functor/Arity, ExCtx, TPred0, _, _),
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_check_for_trivial_fails'(Mode, Pred, TPred0, Head),
functor(TPred0, TFunctor, TArity),
( ( '$lgt_pp_meta_predicate_'(Head, _, _, _) ->
HeadIsMeta = true
; HeadIsMeta = false
),
'$lgt_pp_meta_predicate_'(Pred, Meta, _, _),
% local user-defined meta-predicate
Pred =.. [Functor| Args],
Meta =.. [Functor| MArgs],
'$lgt_wrap_local_meta_arguments'(MArgs, Args, HeadIsMeta, Caller, Ctx, TArgs0) ->
'$lgt_append'(TArgs0, [ExCtx], TArgs),
TPred =.. [TFunctor| TArgs]
; % non meta-predicate or runtime compilation of meta-arguments
TPred = TPred0
),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TFunctor/TArity, Head).
% call to a foreign predicate but only when compiling a module as an object;
% this is fragile due to the lack of standards for Prolog foreign language interfaces;
% moreover, not all backend Prolog systems support a "foreign" predicate property
'$lgt_compile_body'(Pred, _, Pred, '$lgt_debug'(goal(Pred, Pred), ExCtx), Ctx) :-
'$lgt_pp_module_'(_),
% not all backend Prolog systems support a "foreign" predicate property
catch('$lgt_predicate_property'(Pred, foreign), _, fail),
\+ '$lgt_prolog_built_in_predicate'(Pred),
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
% implicit call to a module predicate with a missing use_module/2 directive
% but only when compiling a module as an object; in practice, this is only
% usable from backend systems with an autoload mechanism
'$lgt_compile_body'(Pred, _, ':'(Module,Pred), '$lgt_debug'(goal(Pred, ':'(Module,Pred)), ExCtx), Ctx) :-
'$lgt_pp_module_'(Current),
\+ '$lgt_prolog_built_in_predicate'(Pred),
'$lgt_find_visible_module_predicate'(Current, Module, Pred),
!,
functor(Pred, Functor, Arity),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_remember_missing_use_module_directive'(Mode, Module, Functor/Arity).
% call to a declared but undefined predicate
'$lgt_compile_body'(Pred, _, TPred, '$lgt_debug'(goal(Pred, TPred), ExCtx), Ctx) :-
( '$lgt_pp_dynamic_'(Pred, _, _, _)
; '$lgt_pp_multifile_'(Pred, _, _, _)
),
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, _, _),
functor(Pred, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(TPred, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(Pred, TPred, ExCtx),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TFunctor/TArity, Head).
'$lgt_compile_body'(Pred, _, fail, '$lgt_debug'(goal(Pred, fail), ExCtx), Ctx) :-
% take into account the common practice of defining
% Prolog modules that export built-in predicates
( '$lgt_pp_module_'(_) ->
% compiling a module as an object
\+ '$lgt_built_in_predicate'(Pred)
; true
),
functor(Pred, Functor, Arity),
( '$lgt_pp_public_'(Functor, Arity, _, _)
; '$lgt_pp_protected_'(Functor, Arity, _, _)
; '$lgt_pp_private_'(Functor, Arity, _, _)
; '$lgt_pp_synchronized_'(Pred, _, _, _)
; '$lgt_pp_coinductive_head_'(Pred, _, _)
; '$lgt_pp_discontiguous_'(Pred, _, _)
),
!,
% closed-world assumption: calls to static, non-multifile, declared
% but undefined predicates must fail instead of throwing an exception
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, Lines, _),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TFunctor/TArity, Head),
'$lgt_report_undefined_predicate_call'(Mode, Functor/Arity, Lines).
% call to a deprecated Prolog built-in predicate
'$lgt_compile_body'(Pred, Caller, TPred, DPred, Ctx) :-
( '$lgt_prolog_deprecated_built_in_predicate_hook'(Pred, RPred) ->
true
; '$lgt_prolog_deprecated_built_in_predicate'(Pred, RPred)
),
'$lgt_prolog_built_in_predicate'(Pred),
\+ '$lgt_pp_defines_predicate_'(Pred, _, _, _, _, _),
!,
% replace it with a call to the standard alternative
'$lgt_compile_body'(RPred, Caller, TPred, DPred, Ctx),
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
functor(Pred, Functor, Arity),
functor(RPred, RFunctor, RArity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, Functor/Arity, RFunctor/RArity)
)
; true
).
'$lgt_compile_body'(Pred, _, _, _, Ctx) :-
( '$lgt_prolog_deprecated_built_in_predicate_hook'(Pred) ->
true
; '$lgt_prolog_deprecated_built_in_predicate'(Pred)
),
'$lgt_prolog_built_in_predicate'(Pred),
\+ '$lgt_pp_defines_predicate_'(Pred, _, _, _, _, _),
% no standard alternative; just print a warning
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _),
functor(Pred, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, Functor/Arity)
),
fail.
% call to a Prolog built-in predicate
'$lgt_compile_body'(Pred, _, _, _, Ctx) :-
'$lgt_prolog_built_in_predicate'(Pred),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
logtalk_linter_hook(Pred, Flag, File, Lines, Type, Entity, Warning),
nonvar(Flag),
'$lgt_valid_flag'(Flag),
'$lgt_compiler_flag'(Flag, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(Flag), Warning),
fail.
'$lgt_compile_body'(Pred, _, TPred, DPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(Pred),
!,
( ( '$lgt_pp_meta_predicate_'(Pred, Meta, _, _),
Type = predicate
% we're either overriding the original meta-predicate template or working around a
% backend Prolog compiler limitation in providing access to meta-predicate templates
; '$lgt_prolog_meta_predicate'(Pred, Meta, Type)
% built-in Prolog meta-predicate declared in the adapter file in use
; % lack of standardization of the predicate_property/2 predicate
% means that the next call may fail to recognize the predicate as
% a meta-predicate and retrieve a usable meta-predicate template
catch('$lgt_predicate_property'(Pred, meta_predicate(Meta)), _, fail),
Type = predicate
) ->
% meta-predicate
Pred =.. [Functor| Args],
Meta =.. [Functor| MArgs],
( '$lgt_prolog_to_logtalk_meta_argument_specifiers'(MArgs, CMArgs),
( '$lgt_prolog_phrase_predicate'(Pred) ->
NewCaller = phrase
; NewCaller = meta
),
'$lgt_compile_prolog_meta_arguments'(Args, CMArgs, NewCaller, Ctx, TArgs, DArgs) ->
TGoal =.. [Functor| TArgs],
DGoal =.. [Functor| DArgs],
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
TPred = TGoal,
( Type == control_construct ->
DPred = DGoal
; DPred = '$lgt_debug'(goal(Pred, DGoal), ExCtx)
),
'$lgt_check_non_portable_prolog_built_in_call'(Mode, Pred)
; % meta-predicate template is not usable
throw(domain_error(meta_predicate_template, Meta))
)
; % non meta-predicate
TPred = Pred,
DPred = '$lgt_debug'(goal(Pred, Pred), ExCtx),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_check_non_portable_prolog_built_in_call'(Mode, Pred),
'$lgt_check_for_tautology_or_falsehood_goal'(Mode, Pred)
).
% call to a Logtalk built-in predicate (that is not already handled)
'$lgt_compile_body'(Pred, _, Pred, '$lgt_debug'(goal(Pred, Pred), ExCtx), Ctx) :-
'$lgt_logtalk_built_in_predicate'(Pred, _),
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
% call to a unknown predicate
'$lgt_compile_body'(Pred, _, TPred, '$lgt_debug'(goal(Pred, TPred), ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, Lines, _),
functor(Pred, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(TPred, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(Pred, TPred, ExCtx),
'$lgt_remember_called_predicate'(Mode, Functor/Arity, TFunctor/TArity, Head),
'$lgt_report_unknown_predicate_call'(Mode, Functor/Arity, Lines),
!.
% unexpected compilation failure
'$lgt_compile_body'(Pred, _, _, _, _) :-
throw(domain_error(goal, Pred)).
% wrap meta-arguments when a meta-predicate calls another local meta-predicate
% with meta-arguments that are not meta-arguments of the caller
%
% when the caller is not a meta-predicate, no wrapping is required as the
% meta-call context is empty
%
% also optimize bound meta-arguments, which are calls to local predicates,
% when not compiling in debug mode
'$lgt_wrap_local_meta_arguments'([], [], _, _, _, []).
'$lgt_wrap_local_meta_arguments'([MArg| MArgs], [Arg| Args], HeadIsMeta, Caller, Ctx, [WArg| WArgs]) :-
( var(Arg) ->
WArg = Arg
; '$lgt_wrap_local_meta_argument'(MArg, Arg, HeadIsMeta, Caller, Ctx, WArg)
),
'$lgt_wrap_local_meta_arguments'(MArgs, Args, HeadIsMeta, Caller, Ctx, WArgs).
'$lgt_wrap_local_meta_argument'((*), Arg, _, _, _, Arg) :-
!.
'$lgt_wrap_local_meta_argument'((::), Arg, _, _, _, Arg) :-
!.
'$lgt_wrap_local_meta_argument'(MArg, Arg, HeadIsMeta, Caller, Ctx, WArg) :-
( '$lgt_compiler_flag'(debug, off),
'$lgt_compile_static_binding_meta_argument'(MArg, Arg, Caller, Ctx, WArg) ->
true
; HeadIsMeta == true ->
WArg = '$lgt_local'(Arg)
; WArg = Arg
).
% bagof/3 and setof/3 existential quantifiers
'$lgt_compile_quantified_body'(Term^Pred, Caller, Term^TPred, Term^DPred, Ctx) :-
!,
( var(Pred) ->
% meta-call resolved at runtime
'$lgt_compile_body'(Pred, Caller, TPred, DPred, Ctx)
; % we can have Term1^Term2^...^Pred
'$lgt_compile_quantified_body'(Pred, Caller, TPred, DPred, Ctx)
).
'$lgt_compile_quantified_body'(Pred, Caller, TPred, DPred, Ctx) :-
'$lgt_compile_body'(Pred, Caller, TPred, DPred, Ctx).
% compute list of existentially qualified variables not occurring in the qualified goal
'$lgt_missing_existential_variables'(QGoal, Variables, Goal) :-
'$lgt_decompose_quantified_body'(QGoal, Terms, Goal),
term_variables(Terms, ExistentialVariables),
term_variables(Goal, GoalVariables),
'$lgt_filter_missing_existential_variables'(ExistentialVariables, GoalVariables, Variables).
'$lgt_decompose_quantified_body'(Term^Pred, [Term| Terms], Goal) :-
!,
( var(Pred) ->
!,
fail
; '$lgt_decompose_quantified_body'(Pred, Terms, Goal)
).
'$lgt_decompose_quantified_body'(Goal, [], Goal).
'$lgt_filter_missing_existential_variables'([], _, []).
'$lgt_filter_missing_existential_variables'([Variable| ExistentialVariables], GoalVariables, Variables) :-
'$lgt_member_var'(Variable, GoalVariables),
!,
'$lgt_filter_missing_existential_variables'(ExistentialVariables, GoalVariables, Variables).
'$lgt_filter_missing_existential_variables'([Variable| ExistentialVariables], GoalVariables, [Variable| Variables]) :-
'$lgt_filter_missing_existential_variables'(ExistentialVariables, GoalVariables, Variables).
% auxiliary predicate to find a singleton variable in the goal argument of
% bagof/3 and setof/3 calls
'$lgt_singleton_variables_in_meta_argument'(Goal, Singletons, Ctx) :-
Goal \= _/_,
% not a lambda expression
term_variables(Goal, Variables),
'$lgt_comp_ctx_term'(Ctx, Term),
bagof(
Singleton,
'$lgt_singleton_variable_in_meta_argument'(Variables, Term, Singleton),
Singletons
).
'$lgt_singleton_variable_in_meta_argument'([Variable| _], Term, Variable) :-
'$lgt_count_variable_occurrences'(Term, Variable, 1).
'$lgt_singleton_variable_in_meta_argument'([_| Variables], Term, Variable) :-
'$lgt_singleton_variable_in_meta_argument'(Variables, Term, Variable).
% '$lgt_fix_disjunction_left_side'(@var_or_callable, -callable)
%
% check if the compilation of the disjunction left-side produced an if-then or
% a soft-cut (e.g. due to goal-expansion) and fix it if necessary to avoid
% converting the disjunction into an if-then-else or a soft-cut with an else part
'$lgt_fix_disjunction_left_side'(Goal0, Goal) :-
( var(Goal0) ->
Goal = Goal0
; Goal0 = (_ -> _) ->
Goal = (Goal0, true)
; Goal0 = '*->'(_, _),
'$lgt_predicate_property'('*->'(_, _), built_in) ->
Goal = (Goal0, true)
; Goal = Goal0
).
% '$lgt_negated_goal_alternative'(Pred, Alt)
%
% auxiliary table for \+ Goal linter warnings
'$lgt_negated_goal_alternative'(call(Goal), \+ Goal).
'$lgt_negated_goal_alternative'(once(Goal), \+ Goal).
'$lgt_negated_goal_alternative'(Term1 = Term2, Term1 \= Term2).
'$lgt_negated_goal_alternative'(Term1 == Term2, Term1 \== Term2).
'$lgt_negated_goal_alternative'(Term1 =:= Term2, Term1 =\= Term2).
'$lgt_negated_goal_alternative'(var(Term), nonvar(Term)).
% '$lgt_module_qualified_clause'(@nonvar, -atom, -clause, -term, -term)
%
% decomposes a an explicitly module qualified clause
'$lgt_module_qualified_clause'(QClause, Module, Clause, Head, Body) :-
( QClause = (QHead :- Body),
nonvar(QHead),
QHead = ':'(Module,Head) ->
Clause = (Head :- Body)
; QClause = ':'(Module,Head),
Clause = Head,
Body = true
).
% '$lgt_compile_error_method'(+compilation_context, -compound)
%
% compiles a call to one of the built-in error methods;
% these methods are shorthands to context/1 + throw/1
'$lgt_compile_error_method'(Exception, TPred, DPred, Ctx) :-
'$lgt_comp_ctx_head'(Ctx, Head0),
( Head0 = _::Head ->
% object (or category) multifile predicate clause
true
; Head0 = ':'(_,Head) ->
% module multifile predicate clause
true
; % non-multifile predicate
Head0 = Head
),
'$lgt_comp_ctx_head_exec_ctx'(Ctx, ExCtx),
TPred = throw(error(Exception, logtalk(Head, ExCtx))),
DPred = '$lgt_debug'(goal(Exception, TPred), ExCtx).
% '$lgt_check_read_term_options'(@compilation_mode, @predicate_indicator, @term)
%
% check read term options portability
'$lgt_check_read_term_options'(runtime, _, _).
'$lgt_check_read_term_options'(compile(_,_,_), Predicate, Options) :-
( '$lgt_is_list'(Options),
'$lgt_compiler_flag'(portability, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_member'(Option, Options),
nonvar(Option),
\+ '$lgt_iso_spec_read_term_option'(Option) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
non_standard_predicate_option(File, Lines, Type, Entity, Predicate, Option)
)
; true
).
% '$lgt_check_write_term_options'(@compilation_mode, @predicate_indicator, @term)
%
% check write term options portability
'$lgt_check_write_term_options'(runtime, _, _).
'$lgt_check_write_term_options'(compile(_,_,_), Predicate, Options) :-
( '$lgt_is_list'(Options),
'$lgt_compiler_flag'(portability, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_member'(Option, Options),
nonvar(Option),
\+ '$lgt_iso_spec_write_term_option'(Option) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
non_standard_predicate_option(File, Lines, Type, Entity, Predicate, Option)
)
; true
).
% '$lgt_check_open_stream_options'(@compilation_mode, @predicate_indicator, @term)
%
% check open stream options portability
'$lgt_check_open_stream_options'(runtime, _, _).
'$lgt_check_open_stream_options'(compile(_,_,_), Predicate, Options) :-
'$lgt_is_list'(Options),
'$lgt_compiler_flag'(portability, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
( '$lgt_member'(Option, Options),
nonvar(Option),
\+ '$lgt_iso_spec_open_stream_option'(Option) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
non_standard_predicate_option(File, Lines, Type, Entity, Predicate, Option)
)
; true
).
% '$lgt_check_for_meta_predicate_directive'(@compilation_mode, @callable, @term)
%
% remember missing meta_predicate/1 directives
'$lgt_check_for_meta_predicate_directive'(runtime, _, _).
'$lgt_check_for_meta_predicate_directive'(compile(aux,_,_), _, _) :-
!.
'$lgt_check_for_meta_predicate_directive'(compile(user,_,_), _::_, _) :-
% clause for multifile object predicate
!.
'$lgt_check_for_meta_predicate_directive'(compile(user,_,_), ':'(_, _), _) :-
% clause for multifile module predicate
!.
'$lgt_check_for_meta_predicate_directive'(compile(user,_,_), Head, MetaArg) :-
'$lgt_term_template'(Head, Template),
( '$lgt_pp_meta_predicate_'(Template, _, _, _) ->
% meta_predicate/1 directive is present
true
; '$lgt_pp_missing_meta_predicate_directive_'(Template, _, _) ->
% missing meta_predicate/1 directive already recorded
true
; term_variables(MetaArg, MetaArgVars),
term_variables(Head, HeadVars),
'$lgt_member'(MetaArgVar, MetaArgVars),
'$lgt_member_var'(MetaArgVar, HeadVars) ->
% the meta-argument is a head argument
'$lgt_source_file_context'(File, Lines),
% delay reporting to the end of entity compilation to avoid repeated reports for
% the same missing directive when a meta-predicate have two or more clauses
assertz('$lgt_pp_missing_meta_predicate_directive_'(Template, File, Lines))
; true
).
% '$lgt_check_non_portable_prolog_built_in_call'(@compilation_mode, @callable)
%
% remember non-portable Prolog built-in predicate calls
'$lgt_check_non_portable_prolog_built_in_call'(runtime, _).
'$lgt_check_non_portable_prolog_built_in_call'(compile(aux,_,_), _) :-
!.
'$lgt_check_non_portable_prolog_built_in_call'(compile(user,_,_), Pred) :-
( \+ '$lgt_pp_non_portable_predicate_'(Pred, _, _),
% not already recorded as a non portable call
\+ '$lgt_iso_spec_predicate'(Pred) ->
% bona fide non-portable Prolog built-in predicate
'$lgt_term_template'(Pred, Template),
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_non_portable_predicate_'(Template, File, Lines))
; true
).
% '$lgt_check_for_tautology_or_falsehood_goal'(@compilation_mode, @callable)
%
% check for likely typos in ground calls to some Prolog built-in predicates
% that result in either tautologies or falsehoods
'$lgt_check_for_tautology_or_falsehood_goal'(runtime, _).
'$lgt_check_for_tautology_or_falsehood_goal'(compile(aux,_,_), _) :-
!.
'$lgt_check_for_tautology_or_falsehood_goal'(compile(user,_,_), Goal) :-
( ground(Goal),
% exclude already handled linter check for (\=)/2 goals
\+ functor(Goal, (\=), 2),
'$lgt_compiler_flag'(always_true_or_false_goals, warning),
( '$lgt_candidate_tautology_or_falsehood_goal'(Goal)
; '$lgt_candidate_tautology_or_falsehood_goal_hook'(Goal)
) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
( catch(Goal, Error, true) ->
( var(Error) ->
'$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_true(File, Lines, Type, Entity, Goal)
)
; '$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_error(File, Lines, Type, Entity, Goal, Error)
)
)
; '$lgt_print_message'(
warning(always_true_or_false_goals),
goal_is_always_false(File, Lines, Type, Entity, Goal)
)
)
; true
).
% '$lgt_check_for_trivial_fails'(@compilation_mode, @callable, @callable, @callable)
%
% check for trivial fails due to no matching local clause being available for a goal;
% this check is only performed for local static predicates as dynamic or multifile
% predicates can get new clauses at runtime
'$lgt_check_for_trivial_fails'(runtime, _, _, _).
'$lgt_check_for_trivial_fails'(compile(aux,_,_), _, _, _) :-
!.
'$lgt_check_for_trivial_fails'(compile(user,_,_), Goal, TGoal, Head) :-
( '$lgt_compiler_flag'(trivial_goal_fails, warning),
% workaround possible creation of a cyclic term with some backend
% Prolog compilers implementation of the \=2 predicate
copy_term(Head, HeadCopy),
Goal \= HeadCopy,
% not a recursive call which can originate from a predicate with a single clause
\+ '$lgt_pp_dynamic_'(Goal, _, _, _),
\+ '$lgt_pp_multifile_'(Goal, _, _, _),
% not a dynamic or multifile predicate
\+ '$lgt_pp_entity_term_'(fact(TGoal, _), _, _),
\+ '$lgt_pp_entity_term_'(srule(TGoal, _, _), _, _),
\+ '$lgt_pp_entity_term_'(dfact(TGoal, _, _), _, _),
\+ '$lgt_pp_entity_term_'(dsrule(TGoal, _, _, _), _, _),
% not a yet to be compiled user-defined fact or rule
\+ '$lgt_pp_final_entity_term_'(TGoal, _),
\+ '$lgt_pp_final_entity_term_'((TGoal :- _), _),
% not an already compiled user-defined fact or rule
\+ '$lgt_pp_entity_aux_clause_'(fact(TGoal, _)),
\+ '$lgt_pp_entity_aux_clause_'(srule(TGoal, _, _)),
\+ '$lgt_pp_entity_aux_clause_'(dfact(TGoal, _, _)),
\+ '$lgt_pp_entity_aux_clause_'(dsrule(TGoal, _, _, _)),
% not a yet to be compiled auxiliary fact or rule
\+ '$lgt_pp_final_entity_aux_clause_'(TGoal),
\+ '$lgt_pp_final_entity_aux_clause_'((TGoal :- _)) ->
% not an already compiled auxiliary fact or rule
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
( functor(Goal, Functor, Arity),
'$lgt_pp_calls_non_terminal_'(Functor, _, Arity, _) ->
Goal =.. [Functor| GoalArgs],
'$lgt_append'(NonTerminalArgs, [_, _], GoalArgs), !,
NonTerminal =.. [Functor| NonTerminalArgs],
Message = no_matching_clause_for_non_terminal_goal(File, Lines, Type, Entity, NonTerminal)
; Message = no_matching_clause_for_predicate_goal(File, Lines, Type, Entity, Goal)
),
'$lgt_print_message'(warning(trivial_goal_fails), Message)
; true
).
% '$lgt_candidate_tautology_or_falsehood_goal'(@callable)
%
% valid candidates are standard built-in predicates with
% no side-effects when called with ground arguments
% unification
'$lgt_candidate_tautology_or_falsehood_goal'(_ = _).
'$lgt_candidate_tautology_or_falsehood_goal'(unify_with_occurs_check(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(_ \= _).
% term comparison
'$lgt_candidate_tautology_or_falsehood_goal'(_ == _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ \== _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ @< _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ @=< _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ @> _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ @>= _).
% arithmetic comparison
'$lgt_candidate_tautology_or_falsehood_goal'(_ < _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ =< _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ > _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ >= _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ =:= _).
'$lgt_candidate_tautology_or_falsehood_goal'(_ =\= _).
'$lgt_candidate_tautology_or_falsehood_goal'(compare(_, _, _)).
% type testing
'$lgt_candidate_tautology_or_falsehood_goal'(acyclic_term(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(atom(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(atomic(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(callable(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(compound(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(float(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(ground(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(integer(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(nonvar(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(number(_)).
'$lgt_candidate_tautology_or_falsehood_goal'(var(_)).
% term creation and decomposition
'$lgt_candidate_tautology_or_falsehood_goal'(_ =.. _).
'$lgt_candidate_tautology_or_falsehood_goal'(arg(_, _, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(copy_term(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(functor(_, _, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(subsumes_term(_, _)).
% atomic term processing
'$lgt_candidate_tautology_or_falsehood_goal'(atom_length(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(atom_concat(_, _, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(sub_atom(_, _, _, _, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(atom_chars(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(atom_codes(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(char_code(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(number_chars(_, _)).
'$lgt_candidate_tautology_or_falsehood_goal'(number_codes(_, _)).
% '$lgt_remember_called_predicate'(@compilation_mode, +predicate_indicator, +predicate_indicator, @callable)
%
% used for checking calls to undefined predicates and for collecting cross-referencing information
'$lgt_remember_called_predicate'(runtime, _, _, _).
'$lgt_remember_called_predicate'(compile(_,_,_), Functor/Arity, TFunctor/TArity, Head) :-
% currently, the returned line numbers are for the start and end lines of the clause containing the call
( Head = Object::Predicate ->
% call from the body of a Logtalk multifile predicate clause
Caller = Object::HeadFunctor/HeadArity
; Head = ':'(Module,Predicate) ->
% call from the body of a Prolog module multifile predicate clause
Caller = ':'(Module,HeadFunctor/HeadArity)
; % call from the body of a local entity clause
Head = Predicate,
Caller = HeadFunctor/HeadArity
),
functor(Predicate, HeadFunctor, HeadArity),
( '$lgt_source_file_context'(File, Lines) ->
true
; '$lgt_pp_file_paths_flags_'(_, _, File, _, _),
Lines = '-'(0, 0)
),
( Caller == Functor/Arity ->
% recursive call
( retract('$lgt_pp_predicate_recursive_calls_'(Functor, Arity, Count0)) ->
Count is Count0 + 1,
assertz('$lgt_pp_predicate_recursive_calls_'(Functor, Arity, Count))
; assertz('$lgt_pp_predicate_recursive_calls_'(Functor, Arity, 1))
)
; '$lgt_pp_calls_predicate_'(Functor/Arity, _, Caller, File, Lines) ->
% already recorded for the current clause being compiled
true
; assertz('$lgt_pp_calls_predicate_'(Functor/Arity, TFunctor/TArity, Caller, File, Lines))
).
% '$lgt_remember_called_self_predicate'(@compilation_mode, +predicate_indicator, @callable)
%
% used for checking calls to undefined predicates and for collecting cross-referencing information
'$lgt_remember_called_self_predicate'(runtime, _, _).
'$lgt_remember_called_self_predicate'(compile(aux,_,_), _, _) :-
!.
'$lgt_remember_called_self_predicate'(compile(user,_,_), Functor/Arity, Head) :-
% currently, the returned line numbers are for the start and end lines of the clause containing the call
( Head = Object::Predicate ->
% call from the body of a Logtalk multifile predicate clause
Caller = Object::HeadFunctor/HeadArity
; Head = ':'(Module,Predicate) ->
% call from the body of a Prolog module multifile predicate clause
Caller = ':'(Module,HeadFunctor/HeadArity)
; % call from the body of a local entity clause
Head = Predicate,
Caller = HeadFunctor/HeadArity
),
functor(Predicate, HeadFunctor, HeadArity),
'$lgt_source_file_context'(File, Lines),
( '$lgt_pp_calls_self_predicate_'(Functor/Arity, Caller, File, Lines) ->
% already recorded for the current clause being compiled (however unlikely!)
true
; assertz('$lgt_pp_calls_self_predicate_'(Functor/Arity, Caller, File, Lines))
).
% '$lgt_remember_called_super_predicate'(@compilation_mode, +predicate_indicator, @callable)
%
% used for checking calls to undefined predicates and for collecting cross-referencing information
'$lgt_remember_called_super_predicate'(runtime, _, _).
'$lgt_remember_called_super_predicate'(compile(aux,_,_), _, _) :-
!.
'$lgt_remember_called_super_predicate'(compile(user,_,_), Functor/Arity, Head) :-
% currently, the returned line numbers are for the start and end lines of the clause containing the call
( Head = Object::Predicate ->
% call from the body of a Logtalk multifile predicate clause
Caller = Object::HeadFunctor/HeadArity
; Head = ':'(Module,Predicate) ->
% call from the body of a Prolog module multifile predicate clause
Caller = ':'(Module,HeadFunctor/HeadArity)
; % call from the body of a local entity clause
Head = Predicate,
Caller = HeadFunctor/HeadArity
),
functor(Predicate, HeadFunctor, HeadArity),
'$lgt_source_file_context'(File, Lines),
( '$lgt_pp_calls_super_predicate_'(Functor/Arity, Caller, File, Lines) ->
% already recorded for the current clause being compiled (however unlikely!)
true
; assertz('$lgt_pp_calls_super_predicate_'(Functor/Arity, Caller, File, Lines))
).
% '$lgt_remember_missing_use_module_directive'(@compilation_mode, +atom, +predicate_indicator)
%
% used only for reporting implicit calls to module predicates with missing use_module/2
% directives when compiling modules as objects
'$lgt_remember_missing_use_module_directive'(runtime, _, _).
'$lgt_remember_missing_use_module_directive'(compile(aux,_,_), _, _) :-
!.
'$lgt_remember_missing_use_module_directive'(compile(user,_,_), Module, Functor/Arity) :-
( '$lgt_pp_missing_use_module_directive_'(Module, Functor/Arity) ->
% already recorded
true
; assertz('$lgt_pp_missing_use_module_directive_'(Module, Functor/Arity))
).
% '$lgt_remember_updated_predicate'(@compilation_mode, @term, @callable)
%
% used for collecting cross-referencing information
'$lgt_remember_updated_predicate'(runtime, _, _).
'$lgt_remember_updated_predicate'(compile(aux,_,_), _, _) :-
!.
'$lgt_remember_updated_predicate'(compile(user,_,_), Dynamic, Head) :-
% currently, the returned line numbers are for the start and end lines of the clause containing the call
( Head = Object::Predicate ->
% update from the body of a Logtalk multifile predicate clause
Updater = Object::HeadFunctor/HeadArity
; Head = ':'(Module,Predicate) ->
% update from the body of a Prolog module multifile predicate clause
Updater = ':'(Module,HeadFunctor/HeadArity)
; % update from the body of a local entity clause
Head = Predicate,
Updater = HeadFunctor/HeadArity
),
functor(Predicate, HeadFunctor, HeadArity),
'$lgt_source_file_context'(File, Lines),
( '$lgt_pp_updates_predicate_'(Dynamic, Updater, File, Lines) ->
% already recorded for the current clause being compiled (however unlikely!)
true
; assertz('$lgt_pp_updates_predicate_'(Dynamic, Updater, File, Lines))
).
% '$lgt_bagof'(?term, ?term, ?term, +execution_context, +atom)
%
% handles bagof/3 calls with goals only known at runtime
'$lgt_bagof'(Term, QGoal, List, ExCtx, Where) :-
'$lgt_convert_quantified_goal'(QGoal, Goal, '$lgt_quantified_metacall'(Goal, ExCtx, Where), TQGoal),
bagof(Term, TQGoal, List).
% '$lgt_setof'(?term, ?term, ?term, +execution_context)
%
% handles setof/3 calls with goals only known at runtime
'$lgt_setof'(Term, QGoal, List, ExCtx, Where) :-
'$lgt_convert_quantified_goal'(QGoal, Goal, '$lgt_quantified_metacall'(Goal, ExCtx, Where), TQGoal),
setof(Term, TQGoal, List).
% '$lgt_convert_quantified_goal'(@callable, -callable, +callable, -callable)
%
% converts a ^/2 goal at runtime (used with bagof/3 and setof/3 calls)
%
% returns both the original goal without existential variables and the compiled
% goal that will be used as the argument for the bagof/3 and setof/3 calls
'$lgt_convert_quantified_goal'(Goal, Goal, TGoal, TGoal) :-
var(Goal),
!.
'$lgt_convert_quantified_goal'(Var^Term, Goal, TGoal, Var^TTerm) :-
!,
'$lgt_convert_quantified_goal'(Term, Goal, TGoal, TTerm).
'$lgt_convert_quantified_goal'(Goal, Goal, TGoal, TGoal).
% '$lgt_generate_aux_predicate_functor'(+atom, -atom)
%
% generates a new functor for an auxiliary predicate
% based on a base atom and an entity global counter
'$lgt_generate_aux_predicate_functor'(Base, Functor) :-
( retract('$lgt_pp_aux_predicate_counter_'(Old)) ->
New is Old + 1
; New is 1
),
asserta('$lgt_pp_aux_predicate_counter_'(New)),
number_codes(New, NewCodes),
atom_codes(NewAtom, NewCodes),
atom_concat(Base, NewAtom, Functor).
% '$lgt_compile_bb_key'(@term, +atom, -atom)
%
% compile-time translation of a blackboard key
'$lgt_compile_bb_key'(Key, Prefix, TKey) :-
( atom(Key) ->
atom_concat(Prefix, Key, TKey)
; integer(Key) ->
number_codes(Key, KeyCodes),
atom_codes(AtomKey, KeyCodes),
atom_concat(Prefix, AtomKey, TKey)
; throw(type_error(atomic, Key))
).
% '$lgt_compile_bb_key'(@term, +atom, -atom, @callable)
%
% runtime translation of a blackboard key
'$lgt_compile_bb_key'(Key, Prefix, TKey, Goal) :-
( var(Key) ->
throw(error(instantiation_error, Goal))
; atomic(Key) ->
'$lgt_compile_bb_key'(Key, Prefix, TKey)
; throw(error(type_error(atomic, Key), Goal))
).
% '$lgt_threaded'(+callable, +execution_context, +atom)
%
% handling of threaded/1 calls when the argument is only bound at runtime
'$lgt_threaded'(Goals, ExCtx, Where) :-
( var(Goals) ->
throw(error(instantiation_error, threaded(Goals)))
; \+ callable(Goals) ->
throw(error(type_error(callable, Goals), threaded(Goals)))
; '$lgt_runtime_threaded_call'(Goals, MTGoals, ExCtx, Where),
call(MTGoals)
).
% '$lgt_runtime_threaded_call'(+callable, -callable, +execution_context, +atom)
%
% runtime compilation of the argument of a call to the built-in predicate threaded/1
'$lgt_runtime_threaded_call'((Goal; Goals), '$lgt_threaded_or'(Queue, MTGoals, Results), ExCtx, Where) :-
!,
'$lgt_runtime_threaded_or_call'((Goal; Goals), Queue, MTGoals, Results, ExCtx, Where).
'$lgt_runtime_threaded_call'((Goal, Goals), '$lgt_threaded_and'(Queue, MTGoals, Results), ExCtx, Where) :-
!,
'$lgt_runtime_threaded_and_call'((Goal, Goals), Queue, MTGoals, Results, ExCtx, Where).
'$lgt_runtime_threaded_call'(Goal, ('$lgt_metacall'(Goal, ExCtx, Where) -> true; fail), ExCtx, Where).
'$lgt_runtime_threaded_or_call'((Goal; Goals), Queue, (MTGoal, MTGoals), [Result| Results], ExCtx, Where) :-
!,
'$lgt_runtime_threaded_goal'(Goal, Queue, MTGoal, Result, ExCtx, Where),
'$lgt_runtime_threaded_or_call'(Goals, Queue, MTGoals, Results, ExCtx, Where).
'$lgt_runtime_threaded_or_call'(Goal, Queue, MTGoal, [Result], ExCtx, Where) :-
'$lgt_runtime_threaded_goal'(Goal, Queue, MTGoal, Result, ExCtx, Where).
'$lgt_runtime_threaded_and_call'((Goal, Goals), Queue, (MTGoal, MTGoals), [Result| Results], ExCtx, Where) :-
!,
'$lgt_runtime_threaded_goal'(Goal, Queue, MTGoal, Result, ExCtx, Where),
'$lgt_runtime_threaded_and_call'(Goals, Queue, MTGoals, Results, ExCtx, Where).
'$lgt_runtime_threaded_and_call'(Goal, Queue, MTGoal, [Result], ExCtx, Where) :-
'$lgt_runtime_threaded_goal'(Goal, Queue, MTGoal, Result, ExCtx, Where).
'$lgt_runtime_threaded_goal'(Goal, Queue, '$lgt_threaded_goal'('$lgt_metacall'(Goal, ExCtx, Where), TVars, Queue, Id), id(Id, TVars, _), ExCtx, Where).
% '$lgt_compile_threaded_call'(+callable, -callable)
%
% compiles the argument of a call to the built-in predicate threaded/1
'$lgt_compile_threaded_call'((TGoal; TGoals), '$lgt_threaded_or'(Queue, MTGoals, Results)) :-
!,
'$lgt_compile_threaded_or_call'((TGoal; TGoals), Queue, MTGoals, Results).
'$lgt_compile_threaded_call'((TGoal, TGoals), '$lgt_threaded_and'(Queue, MTGoals, Results)) :-
!,
'$lgt_compile_threaded_and_call'((TGoal, TGoals), Queue, MTGoals, Results).
'$lgt_compile_threaded_call'(TGoal, (TGoal -> true; fail)).
'$lgt_compile_threaded_or_call'((TGoal; TGoals), Queue, (MTGoal, MTGoals), [Result| Results]) :-
!,
'$lgt_compile_threaded_goal'(TGoal, Queue, MTGoal, Result),
'$lgt_compile_threaded_or_call'(TGoals, Queue, MTGoals, Results).
'$lgt_compile_threaded_or_call'(TGoal, Queue, MTGoal, [Result]) :-
'$lgt_compile_threaded_goal'(TGoal, Queue, MTGoal, Result).
'$lgt_compile_threaded_and_call'((TGoal, TGoals), Queue, (MTGoal, MTGoals), [Result| Results]) :-
!,
'$lgt_compile_threaded_goal'(TGoal, Queue, MTGoal, Result),
'$lgt_compile_threaded_and_call'(TGoals, Queue, MTGoals, Results).
'$lgt_compile_threaded_and_call'(TGoal, Queue, MTGoal, [Result]) :-
'$lgt_compile_threaded_goal'(TGoal, Queue, MTGoal, Result).
'$lgt_compile_threaded_goal'(TGoal, Queue, '$lgt_threaded_goal'(TGoal, TVars, Queue, Id), id(Id, TVars, _)).
% '$lgt_compile_prolog_meta_arguments'(@list, @list, +callable, +compilation_context, -list, -list)
%
% compiles the meta-arguments contained in the list of arguments of a call to a Prolog
% meta-predicate or meta-directive (assumes Logtalk meta-predicate notation)
%
% this predicate fails when meta-arguments other than goal and closures are not
% sufficiently instantiated or a meta-argument mode indicator is not supported
'$lgt_compile_prolog_meta_arguments'([], [], _, _, [], []).
'$lgt_compile_prolog_meta_arguments'([Arg| Args], [MArg| MArgs], Caller, Ctx, [TArg| TArgs], [DArg| DArgs]) :-
( nonvar(Arg),
'$lgt_module_meta_argument'(MArg, Arg),
'$lgt_prolog_feature'(modules, supported) ->
% explicitly-qualified meta-argument
TArg = Arg, DArg = Arg
; integer(MArg),
MArg > 0 ->
% closure meta-argument
'$lgt_compile_prolog_meta_argument'(closure(MArg), Arg, Caller, Ctx, TArg, DArg)
; % remaining cases
'$lgt_compile_prolog_meta_argument'(MArg, Arg, Caller, Ctx, TArg, DArg)
),
'$lgt_compile_prolog_meta_arguments'(Args, MArgs, Caller, Ctx, TArgs, DArgs).
'$lgt_module_meta_argument'(0, ':'(_,_)).
'$lgt_module_meta_argument'(1, ':'(_)).
'$lgt_compile_prolog_meta_argument'(closure(N), Arg, Caller, Ctx, TArg, DArg) :-
% closure
'$lgt_check'(var_or_callable, Arg),
'$lgt_length'(ExtArgs, 0, N),
( var(Arg) ->
ExtArg =.. [call, Arg| ExtArgs]
; '$lgt_extend_closure'(Arg, ExtArgs, ExtArg, Ctx) ->
true
; throw(domain_error(closure, Arg))
),
'$lgt_compile_body'(ExtArg, Caller, TArg0, DArg0, Ctx),
% generate an auxiliary predicate to allow the meta-predicate to extend
% the closure without clashing with the execution-context argument
'$lgt_generate_aux_predicate_functor'('_closure_', HelperFunctor),
'$lgt_pp_entity_'(_, _, Prefix),
atom_concat(Prefix, HelperFunctor, THelperFunctor),
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
THelper =.. [THelperFunctor, Arg, ExCtx],
TExtHelper =.. [THelperFunctor, Arg, ExCtx| ExtArgs],
( '$lgt_compiler_flag'(debug, on) ->
assertz('$lgt_pp_entity_aux_clause_'({(TExtHelper :- DArg0)}))
; assertz('$lgt_pp_entity_aux_clause_'({(TExtHelper :- TArg0)}))
),
( '$lgt_pp_object_'(Entity, _, _, Def, _, _, _, _, _, _, _) ->
true
; '$lgt_pp_category_'(Entity, _, _, Def, _, _)
),
% add a def clause to ensure that we don't loose track of the auxiliary clause
Arity is N + 2,
'$lgt_length'(TemplateArgs, 0, Arity),
ExtHelperTemplate =.. [HelperFunctor| TemplateArgs],
TExtHelperTemplate =.. [THelperFunctor| TemplateArgs],
Clause =.. [Def, ExtHelperTemplate, _, TExtHelperTemplate],
assertz('$lgt_pp_def_'(Clause)),
% add, if applicable, source data information for the auxiliary clause
( '$lgt_compiler_flag'(source_data, on) ->
assertz('$lgt_pp_runtime_clause_'('$lgt_predicate_property_'(Entity, HelperFunctor/Arity, flags_clauses_rules_location(1,1,1,0-0))))
; true
),
( '$lgt_prolog_feature'(modules, supported) ->
% make sure the calls are made in the correct context
'$lgt_user_module_qualification'(THelper, TArg),
'$lgt_user_module_qualification'(THelper, DArg)
; TArg = THelper,
DArg = THelper
).
% normal (non-meta) argument
'$lgt_compile_prolog_meta_argument'((*), Arg, _, _, Arg, Arg).
% goal
'$lgt_compile_prolog_meta_argument'((0), Arg, Caller, Ctx, TArg, DArg) :-
'$lgt_compile_body'(Arg, Caller, TArg0, DArg0, Ctx),
( TArg0 = ':'(_, _) ->
% the compiled call is already explicitly-qualified
TArg = TArg0,
DArg = DArg0
; '$lgt_prolog_feature'(modules, supported) ->
% make sure the calls are made in the correct context
'$lgt_user_module_qualification'(TArg0, TArg),
'$lgt_user_module_qualification'(DArg0, DArg)
; TArg = TArg0,
DArg = DArg0
).
% existentially-quantified goal
'$lgt_compile_prolog_meta_argument'((^), Arg, Caller, Ctx, TArg, DArg) :-
( Arg = Vars^Arg0 ->
'$lgt_compile_body'(Arg0, Caller, TArg0, DArg0, Ctx),
TArg = Vars^TArg0,
DArg = Vars^DArg0
; '$lgt_compile_body'(Arg, Caller, TArg, DArg, Ctx)
).
% list of goals
'$lgt_compile_prolog_meta_argument'([0], [], _, _, [], []) :-
!.
'$lgt_compile_prolog_meta_argument'([0], [Arg| Args], Caller, Ctx, [TArg| TArgs], [DArg| DArgs]) :-
!,
'$lgt_compile_prolog_meta_argument'((0), Arg, Caller, Ctx, TArg, DArg),
'$lgt_compile_prolog_meta_argument'([0], Args, Caller, Ctx, TArgs, DArgs).
% predicate indicator
'$lgt_compile_prolog_meta_argument'((/), [Arg| Args], Caller, Ctx, [TArg| TArgs], [DArg| DArgs]) :-
!,
nonvar(Arg),
'$lgt_compile_prolog_meta_argument'((/), Arg, Caller, Ctx, TArg, DArg),
'$lgt_compile_prolog_meta_argument'([/], Args, Caller, Ctx, TArgs, DArgs).
'$lgt_compile_prolog_meta_argument'((/), (Arg, Args), Caller, Ctx, (TArg, TArgs), (DArg, DArgs)) :-
!,
nonvar(Arg),
'$lgt_compile_prolog_meta_argument'((/), Arg, Caller, Ctx, TArg, DArg),
'$lgt_compile_prolog_meta_argument'((/), Args, Caller, Ctx, TArgs, DArgs).
'$lgt_compile_prolog_meta_argument'((/), Arg, _, _, TArg, TArg) :-
'$lgt_compile_predicate_indicators'(Arg, _, TArg0),
( '$lgt_prolog_feature'(modules, supported) ->
% make sure the predicate indicator refers to the correct context
'$lgt_user_module_qualification'(TArg0, TArg)
; TArg = TArg0
).
% non-terminal indicator
'$lgt_compile_prolog_meta_argument'((//), Args, Caller, Ctx, TArgs, DArgs) :-
'$lgt_compile_prolog_meta_argument'((/), Args, Caller, Ctx, TArgs, DArgs).
% list of predicate indicators
'$lgt_compile_prolog_meta_argument'([/], [], _, _, [], []) :-
!.
'$lgt_compile_prolog_meta_argument'([/], [Arg| Args], Caller, Ctx, [TArg| TArgs], [DArg| DArgs]) :-
!,
nonvar(Arg),
'$lgt_compile_prolog_meta_argument'((/), Arg, Caller, Ctx, TArg, DArg),
'$lgt_compile_prolog_meta_argument'([/], Args, Caller, Ctx, TArgs, DArgs).
% list of non-terminal indicators
'$lgt_compile_prolog_meta_argument'([//], Args, Caller, Ctx, TArgs, DArgs) :-
'$lgt_compile_prolog_meta_argument'([/], Args, Caller, Ctx, TArgs, DArgs).
% '$lgt_extend_closure'(@callable, @list(term), -callable, +compilation_context)
%
% extends a closure by appending a list of arguments to construct a goal
%
% this predicate fails if the closure can only be extended at runtime
'$lgt_extend_closure'(Closure, _, _, _) :-
var(Closure),
!,
fail.
'$lgt_extend_closure'(Obj::Closure, ExtArgs, Goal, Ctx) :-
Obj == user,
!,
'$lgt_extend_closure'({Closure}, ExtArgs, Goal, Ctx).
'$lgt_extend_closure'(Obj::Closure, ExtArgs, Obj::Msg, _) :-
!,
'$lgt_extend_closure_basic'(Closure, ExtArgs, Msg).
'$lgt_extend_closure'([Obj::Closure], ExtArgs, [Obj::Msg], _) :-
!,
'$lgt_extend_closure_basic'(Closure, ExtArgs, Msg).
'$lgt_extend_closure'(::Closure, ExtArgs, ::Msg, _) :-
!,
'$lgt_extend_closure_basic'(Closure, ExtArgs, Msg).
'$lgt_extend_closure'(^^Closure, ExtArgs, ^^Msg, _) :-
!,
'$lgt_extend_closure_basic'(Closure, ExtArgs, Msg).
'$lgt_extend_closure'(Obj<>Lambda, ExtArgs, Goal, _) :-
!,
Goal =.. [call, Parameters>>Lambda| ExtArgs].
'$lgt_extend_closure'(':'(Module,Closure), ExtArgs, ':'(Module,Goal), _) :-
!,
'$lgt_extend_closure_basic'(Closure, ExtArgs, Goal).
'$lgt_extend_closure'(Closure, ExtArgs, Goal, Ctx) :-
'$lgt_extend_closure_basic'(Closure, ExtArgs, Alias),
( '$lgt_pp_uses_predicate_'(Object, Original, Alias, Ctx, _, _),
( Original == Alias ->
% no alias is defined
true
; % check that we're renaming a predicate but not (also) changing its argument order as that
% would break using the closure as a meta-argument when appending the additional arguments
Original =.. [_| OriginalArguments],
Alias =.. [_| AliasArguments],
OriginalArguments == AliasArguments
) ->
Goal = Object::Original
; '$lgt_pp_use_module_predicate_'(Module, Original, Alias, Ctx, _, _),
( Original == Alias ->
% no alias is defined
true
; % check that we're renaming a predicate but not (also) changing its argument order as that
% would break using the closure as a meta-argument when appending the additional arguments
Original =.. [_| OriginalArguments],
Alias =.. [_| AliasArguments],
OriginalArguments == AliasArguments
) ->
Goal = ':'(Module, Original)
; Goal = Alias
).
'$lgt_extend_closure_basic'(Closure, ExtArgs, Goal) :-
callable(Closure),
% compile-time closure extension possible
Closure =.. [Functor| Args],
'$lgt_append'(Args, ExtArgs, FullArgs),
Goal =.. [Functor| FullArgs].
% '$lgt_not_same_meta_arg_extra_args'(@list(nonvar), @list(var), @var, +integer)
%
% checks that the number of additional arguments being appended to a closure
% in a call/N call matches the corresponding meta-predicate declaration
% (the relative ordering of the meta-vars is the same of the corresponding
% meta-arguments; assumes Logtalk meta-predicate notation)
'$lgt_not_same_meta_arg_extra_args'([(*)| MetaArgs], MetaVars, Closure, ExtraArgs) :-
!,
'$lgt_not_same_meta_arg_extra_args'(MetaArgs, MetaVars, Closure, ExtraArgs).
'$lgt_not_same_meta_arg_extra_args'([(::)| MetaArgs], MetaVars, Closure, ExtraArgs) :-
!,
'$lgt_not_same_meta_arg_extra_args'(MetaArgs, MetaVars, Closure, ExtraArgs).
'$lgt_not_same_meta_arg_extra_args'([0| MetaArgs], MetaVars, Closure, ExtraArgs) :-
!,
'$lgt_not_same_meta_arg_extra_args'(MetaArgs, MetaVars, Closure, ExtraArgs).
'$lgt_not_same_meta_arg_extra_args'([MetaArg| _], [MetaVar| _], Closure, ExtraArgs) :-
MetaVar == Closure,
!,
integer(MetaArg),
MetaArg =\= ExtraArgs.
'$lgt_not_same_meta_arg_extra_args'([_| MetaArgs], [_| MetaVars], Closure, ExtraArgs) :-
'$lgt_not_same_meta_arg_extra_args'(MetaArgs, MetaVars, Closure, ExtraArgs).
% '$lgt_same_number_of_closure_extra_args'(@list, @list, @list, @list, @callable, @callable)
%
% checks that the number of additional arguments being appended to a closure is kept
% when passing a closure from the clause head to a meta-predicate call in the body
'$lgt_same_number_of_closure_extra_args'([], _, _, _, _, _).
'$lgt_same_number_of_closure_extra_args'([PredArg| PredArgs], [PredMetaArg| PredMetaArgs], HeadArgs, HeadMetaArgs, HeadMeta, PredMeta) :-
( var(PredArg),
integer(PredMetaArg), PredMetaArg > 0,
% argument is a closure
'$lgt_shared_closure_arg'(PredArg, HeadArgs, HeadMetaArgs, HeadMetaArg) ->
% shared closure argument
( PredMetaArg = HeadMetaArg ->
% same number of closure extra args
'$lgt_same_number_of_closure_extra_args'(PredArgs, PredMetaArgs, HeadArgs, HeadMetaArgs, HeadMeta, PredMeta)
; throw(consistency_error(same_closure_specification, HeadMeta, PredMeta))
)
; '$lgt_same_number_of_closure_extra_args'(PredArgs, PredMetaArgs, HeadArgs, HeadMetaArgs, HeadMeta, PredMeta)
).
'$lgt_shared_closure_arg'(PredArg, [HeadArg| _], [HeadMetaArg| _], HeadMetaArg) :-
PredArg == HeadArg.
'$lgt_shared_closure_arg'(PredArg, [_| HeadArgs], [_| HeadMetaArgs], HeadMetaArg) :-
'$lgt_shared_closure_arg'(PredArg, HeadArgs, HeadMetaArgs, HeadMetaArg).
% '$lgt_check_dynamic_directive'(@compilation_mode, @term)
%
% checks for a dynamic/1 directive for a predicate that is an argument to the
% database built-in methods; the predicate may be non-instantiated or only
% partially instantiated but must be valid
'$lgt_check_dynamic_directive'(runtime, _).
'$lgt_check_dynamic_directive'(compile(_,_,_), Term) :-
'$lgt_check_dynamic_directive'(Term).
'$lgt_check_dynamic_directive'(Term) :-
var(Term),
% runtime binding argument
!.
'$lgt_check_dynamic_directive'((Head :- _)) :-
!,
'$lgt_check_dynamic_directive'(Head).
'$lgt_check_dynamic_directive'(Functor/Arity) :-
!,
( ground(Functor/Arity) ->
functor(Head, Functor, Arity),
'$lgt_check_dynamic_directive'(Head)
; true
).
'$lgt_check_dynamic_directive'(Head) :-
( '$lgt_pp_dynamic_'(Head, _, _, _) ->
% dynamic/1 directive is present
true
; '$lgt_pp_missing_dynamic_directive_'(Head, _, _) ->
% missing dynamic/1 directive already recorded
true
; '$lgt_pp_entity_'(category, _, _),
% database predicates act only on objects
functor(Head, Functor, Arity),
\+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _) ->
% no scope directive
true
; '$lgt_term_template'(Head, Template),
'$lgt_source_file_context'(File, Lines),
% delay reporting to the end of entity compilation to avoid repeated reports for
% the same missing directive when a dynamic predicate have two or more clauses
assertz('$lgt_pp_missing_dynamic_directive_'(Template, File, Lines))
).
% '$lgt_check_discontiguous_directive'(@callable, @compilation_context)
%
% checks for a discontiguous/1 directive for a predicate
'$lgt_check_discontiguous_directive'(Head, Ctx) :-
'$lgt_term_template'(Head, Template),
retractall('$lgt_pp_previous_predicate_'(_, user)),
assertz('$lgt_pp_previous_predicate_'(Template, user)),
( '$lgt_pp_discontiguous_'(Template, _, _) ->
% discontiguous directive present
true
; '$lgt_pp_missing_discontiguous_directive_'(Template, _, _) ->
% missing discontiguous/1 directive already recorded
true
; '$lgt_comp_ctx_mode'(Ctx, compile(user,_,_)) ->
% compiling a source file clause; record missing discontiguous directive
'$lgt_source_file_context'(File, Lines),
% delay reporting to the end of entity compilation to avoid repeated reports for the same
% missing directive when there multiple discontiguous blocks for the same predicate
assertz('$lgt_pp_missing_discontiguous_directive_'(Template, File, Lines))
; % runtime compilation or compiling an auxiliary predicate clause
true
).
% '$lgt_optimizable_local_db_call'(@term, -callable)
%
% checks if a call to a database built-in method can be optimized by direct
% translation to a call to the corresponding Prolog built-in predicate
'$lgt_optimizable_local_db_call'(Pred, TPred) :-
nonvar(Pred),
% only for objects
'$lgt_pp_entity_'(object, _, Prefix),
% only for facts
( Pred = (Head :- Body) ->
Body == true
; Head = Pred
),
callable(Head),
% a dynamic directive must be present
'$lgt_pp_dynamic_'(Head, _, _, _),
% a scope directive must be present
functor(Head, Functor, Arity),
( '$lgt_pp_public_'(Functor, Arity, _, _)
; '$lgt_pp_protected_'(Functor, Arity, _, _)
; '$lgt_pp_private_'(Functor, Arity, _, _)
), !,
% not compiled in debug mode
'$lgt_compiler_flag'(debug, off),
% compile the fact
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(TPred, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(Head, TPred, _).
% '$lgt_db_call_database_execution_context'(@term, @term, -term, +execution_context)
%
% returns the database where a database method call should take place and sets the
% execution context accordingly
%
% this auxiliary predicate ensures that, when calling database methods in the body
% of a multifile predicate clause defined in an object, the object database will be
% used instead of the database of the entity holding the multifile predicate primary
% declaration (which could be a category, making the calls invalid)
'$lgt_db_call_database_execution_context'(Entity, This, Database, ExCtx) :-
( '$lgt_pp_entity_'(object, _, _) ->
Database = Entity,
'$lgt_execution_context_this_entity'(ExCtx, _, Entity)
; % category
Database = This,
'$lgt_execution_context_this_entity'(ExCtx, This, _)
).
% '$lgt_runtime_checked_db_clause'(@term)
%
% true if the argument forces runtime validity check
'$lgt_runtime_checked_db_clause'(Pred) :-
var(Pred),
!.
'$lgt_runtime_checked_db_clause'((Head :- Body)) :-
var(Head),
!,
'$lgt_check'(var_or_callable, Body).
'$lgt_runtime_checked_db_clause'((Head :- Body)) :-
var(Body),
'$lgt_check'(var_or_callable, Head).
% '$lgt_check_non_portable_functions'(@term, @compilation_context)
%
% checks an arithmetic expression for calls to non-standard Prolog functions
'$lgt_check_non_portable_functions'(Exp, _) :-
number(Exp),
!.
'$lgt_check_non_portable_functions'(Exp, _) :-
var(Exp),
!.
'$lgt_check_non_portable_functions'(Exp, Ctx) :-
'$lgt_prolog_deprecated_built_in_function'(Exp, Alt),
% standard alternative
once('$lgt_predicate_property'(evaluable_property(_, _), _)),
evaluable_property(Exp, built_in),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _),
functor(Exp, Functor, Arity),
functor(Alt, AltFunctor, AltArity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_function(File, Lines, Type, Entity, Functor/Arity, AltFunctor/AltArity)
),
fail.
'$lgt_check_non_portable_functions'(Exp, Ctx) :-
'$lgt_prolog_deprecated_built_in_function'(Exp),
% no standard alternative
once('$lgt_predicate_property'(evaluable_property(_, _), _)),
evaluable_property(Exp, built_in),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _),
functor(Exp, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_function(File, Lines, Type, Entity, Functor/Arity)
),
fail.
'$lgt_check_non_portable_functions'(Exp, Ctx) :-
( '$lgt_pp_missing_function_'(Exp, _, _) ->
% missing function already recorded
true
; '$lgt_predicate_property'(evaluable_property(_, _), _),
\+ evaluable_property(Exp, _) ->
% first occurrence of this missing function; record it
'$lgt_term_template'(Exp, Template),
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_missing_function_'(Template, File, Lines))
; % no reliable way of checking if the function is missing
true
),
( '$lgt_iso_spec_function'(Exp) ->
% portable call (we assume...!)
true
; '$lgt_pp_non_portable_function_'(Exp, _, _) ->
% non-portable function already recorded
true
; % first occurrence of this non-portable function; record it
'$lgt_term_template'(Exp, Template),
'$lgt_source_file_context'(File, Lines),
assertz('$lgt_pp_non_portable_function_'(Template, File, Lines))
),
( Exp = [_|_] ->
% avoid duplicated warnings with the Prolog legacy use of a list
% with a single character to represent the code of the character
true
; Exp =.. [_| Exps],
'$lgt_check_non_portable_function_args'(Exps, Ctx)
).
'$lgt_check_non_portable_function_args'([], _).
'$lgt_check_non_portable_function_args'([Exp| Exps], Ctx) :-
'$lgt_check_non_portable_functions'(Exp, Ctx),
'$lgt_check_non_portable_function_args'(Exps, Ctx).
% '$lgt_compile_message_to_object'(@term, @object_identifier, -callable, +atom, +compilation_context)
%
% compiles a message sending call
% messages to the pseudo-object "user"
'$lgt_compile_message_to_object'(Pred, Obj, _, _, Ctx) :-
Obj == user,
'$lgt_check'(var_or_callable, Pred),
callable(Pred),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_iso_spec_predicate'(Pred),
\+ '$lgt_built_in_method'(Pred, _, _, _),
\+ '$lgt_pp_defines_predicate_'(Pred, _, _, _, _, _),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, user::Pred, [Pred])
),
fail.
'$lgt_compile_message_to_object'(Pred, Obj, TPred, _, Ctx) :-
Obj == user,
callable(Pred),
!,
( \+ '$lgt_prolog_built_in_database_predicate'(Pred),
% the meta-predicate templates for the backend Prolog database predicates are
% usually not usable from Logtalk due the ambiguity of the ":" meta-argument
% qualifier but they pose no problems when operating in "user"; in this
% particular case, the call can be compiled as-is
( '$lgt_prolog_meta_predicate'(Pred, Meta, _)
% built-in Prolog meta-predicate declared in the adapter file in use
; catch('$lgt_predicate_property'(Pred, meta_predicate(Meta)), _, fail)
% Prolog meta-predicate undeclared in the adapter file (may not be a built-in)
; '$lgt_pp_meta_predicate_'(user::Pred, user::Meta, _, _)
% we're either providing a meta-predicate template or overriding the original
% meta-predicate template
) ->
% meta-predicate
Pred =.. [Functor| Args],
Meta =.. [Functor| MArgs],
( '$lgt_prolog_to_logtalk_meta_argument_specifiers'(MArgs, CMArgs),
'$lgt_compile_prolog_meta_arguments'(Args, CMArgs, meta, Ctx, TArgs, _) ->
TPred =.. [Functor| TArgs]
; % meta-predicate template is not usable
throw(domain_error(meta_predicate_template, Meta))
)
; % non meta-predicate
TPred = Pred
),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
( '$lgt_prolog_built_in_database_predicate'(Pred) ->
% update to a dynamic predicate in "user" declared in a uses/2 directive
true
; '$lgt_add_referenced_object_message'(Mode, Obj, Pred, Pred, Head)
).
% suppress debug messages when compiling in optimized mode
'$lgt_compile_message_to_object'(Pred, Obj, true, _, _) :-
Obj == logtalk,
Pred = print_message(Kind, _, _),
callable(Kind),
functor(Kind, debug, _),
'$lgt_compiler_flag'(optimize, on),
!.
% convenient access to parametric object proxies
'$lgt_compile_message_to_object'(Pred, Obj, (CallProxy, TPred), Events, Ctx) :-
nonvar(Obj),
Obj = {Proxy},
!,
( var(Proxy) ->
CallProxy = call(Proxy)
; callable(Proxy) ->
CallProxy = Proxy
; throw(type_error(callable, Proxy))
),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
'$lgt_compile_message_to_object'(Pred, Proxy, TPred, Events, Ctx).
% type and lint checks
'$lgt_compile_message_to_object'(_, Obj, _, _, Ctx) :-
( callable(Obj) ->
% remember the object receiving the message
'$lgt_add_referenced_object'(Obj, Ctx),
fail
; nonvar(Obj),
% invalid object identifier
throw(type_error(object_identifier, Obj))
).
% suspicious use of ::/2 instead of ::/1 to send a message to "self"
'$lgt_compile_message_to_object'(Pred, Obj, _, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, compile(_,_,_), _, _, _),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_execution_context'(ExCtx, _, _, _, Self, _, _),
Self == Obj,
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Obj::Pred, [::Pred])
),
fail.
% suspicious use of ::/2 in objects to call a local predicate
'$lgt_compile_message_to_object'(Pred, Obj, _, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, ExCtx, compile(_,_,_), _, _, _),
'$lgt_pp_entity_'(object, _, _),
'$lgt_compiler_flag'(suspicious_calls, warning),
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _),
This == Obj,
% message sent from an object to itself
nonvar(Pred),
'$lgt_pp_defines_predicate_'(Pred, _, _, _, _, _),
% local predicate
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, Obj::Pred, [Pred])
),
fail.
% translation performed at runtime
'$lgt_compile_message_to_object'(Pred, Obj, '$lgt_send_to_obj_rt'(Obj, Pred, Events, NewCtx), Events, Ctx) :-
var(Pred),
!,
'$lgt_comp_ctx'(Ctx, Head, _, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, _, Stack, Lines, _),
'$lgt_comp_ctx'(NewCtx, Head, _, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, runtime, Stack, Lines, _).
% broadcasting control constructs
'$lgt_compile_message_to_object'((Pred1, Pred2), Obj, (TPred1, TPred2), Events, Ctx) :-
!,
'$lgt_compile_message_to_object'(Pred1, Obj, TPred1, Events, Ctx),
'$lgt_compile_message_to_object'(Pred2, Obj, TPred2, Events, Ctx).
'$lgt_compile_message_to_object'((Pred1; Pred2), Obj, (TPred1; TPred2), Events, Ctx) :-
!,
'$lgt_compile_message_to_object'(Pred1, Obj, TPred1, Events, Ctx),
'$lgt_compile_message_to_object'(Pred2, Obj, TPred2, Events, Ctx).
'$lgt_compile_message_to_object'((Pred1 -> Pred2), Obj, (TPred1 -> TPred2), Events, Ctx) :-
!,
'$lgt_compile_message_to_object'(Pred1, Obj, TPred1, Events, Ctx),
'$lgt_compile_message_to_object'(Pred2, Obj, TPred2, Events, Ctx).
'$lgt_compile_message_to_object'('*->'(Pred1, Pred2), Obj, '*->'(TPred1, TPred2), Events, Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_compile_message_to_object'(Pred1, Obj, TPred1, Events, Ctx),
'$lgt_compile_message_to_object'(Pred2, Obj, TPred2, Events, Ctx).
% built-in methods that cannot be redefined
'$lgt_compile_message_to_object'(!, Obj, ('$lgt_object_exists'(Obj, !, ExCtx), !), _, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_message_to_object'(true, Obj, ('$lgt_object_exists'(Obj, true, ExCtx), true), _, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_message_to_object'(fail, Obj, ('$lgt_object_exists'(Obj, fail, ExCtx), fail), _, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_message_to_object'(false, Obj, ('$lgt_object_exists'(Obj, false, ExCtx), false), _, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
'$lgt_compile_message_to_object'(repeat, Obj, ('$lgt_object_exists'(Obj, repeat, ExCtx), repeat), _, Ctx) :-
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx).
% reflection built-in predicates
'$lgt_compile_message_to_object'(current_op(Priority, Specifier, Operator), Obj, '$lgt_current_op'(Obj, Priority, Specifier, Operator, This, p(p(p)), ExCtx), _, Ctx) :-
!,
'$lgt_check'(var_or_operator_priority, Priority),
'$lgt_check'(var_or_operator_specifier, Specifier),
'$lgt_check'(var_or_atom, Operator),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _).
'$lgt_compile_message_to_object'(current_predicate(Pred), Obj, '$lgt_current_predicate'(Obj, Pred, This, p(p(p)), ExCtx), _, Ctx) :-
!,
'$lgt_check'(var_or_predicate_indicator, Pred),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _).
'$lgt_compile_message_to_object'(predicate_property(Pred, Prop), Obj, '$lgt_predicate_property'(Obj, Pred, Prop, This, p(p(p)), ExCtx), _, Ctx) :-
!,
'$lgt_check'(var_or_callable, Pred),
'$lgt_check'(var_or_predicate_property, Prop),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _).
% database handling built-in predicates
'$lgt_compile_message_to_object'(abolish(Functor, Arity), Obj, TPred, Events, Ctx) :-
'$lgt_prolog_built_in_predicate'(abolish(_, _)),
\+ '$lgt_pp_defines_predicate_'(abolish(_, _), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, abolish/2, abolish/1)
)
; true
),
'$lgt_compile_message_to_object'(abolish(Functor/Arity), Obj, TPred, Events, Ctx).
'$lgt_compile_message_to_object'(abolish(Pred), Obj, TPred, _, Ctx) :-
!,
'$lgt_check'(var_or_predicate_indicator, Pred),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( var(Obj) ->
TPred = '$lgt_abolish'(Obj, Pred, This, p(p(p)), ExCtx)
; ground(Pred) ->
TPred = '$lgt_abolish_checked'(Obj, Pred, This, p(p(p)), ExCtx),
'$lgt_remember_updated_predicate'(Mode, Obj::Pred, Head)
; % partially instantiated predicate indicator; runtime check required
TPred = '$lgt_abolish'(Obj, Pred, This, p(p(p)), ExCtx)
).
'$lgt_compile_message_to_object'(assert(Clause), Obj, TPred, Events, Ctx) :-
'$lgt_prolog_built_in_predicate'(assert(_)),
\+ '$lgt_pp_defines_predicate_'(assert(_), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, assert/1, assertz/1)
)
; true
),
'$lgt_compile_message_to_object'(assertz(Clause), Obj, TPred, Events, Ctx).
'$lgt_compile_message_to_object'(asserta(Clause), Obj, TPred, _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_asserta'(Obj, Clause, This, p(p(_)), p(p(p)), ExCtx)
; var(Obj) ->
'$lgt_check'(clause, Clause),
TPred = '$lgt_asserta'(Obj, Clause, This, p(p(_)), p(p(p)), ExCtx)
; '$lgt_check'(clause, Clause),
( (Clause = (Head :- Body) -> Body == true; Clause = Head) ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) ->
TPred = asserta(THead)
; TPred = '$lgt_asserta_fact_checked'(Obj, Head, This, p(p(_)), p(p(p)), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; TPred = '$lgt_asserta_rule_checked'(Obj, Clause, This, p(p(_)), p(p(p)), ExCtx),
Clause = (Head :- _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_object'(assertz(Clause), Obj, TPred, _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_assertz'(Obj, Clause, This, p(p(_)), p(p(p)), ExCtx)
; var(Obj) ->
'$lgt_check'(clause, Clause),
TPred = '$lgt_assertz'(Obj, Clause, This, p(p(_)), p(p(p)), ExCtx)
; '$lgt_check'(clause, Clause),
( (Clause = (Head :- Body) -> Body == true; Clause = Head) ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) ->
TPred = assertz(THead)
; TPred = '$lgt_assertz_fact_checked'(Obj, Head, This, p(p(_)), p(p(p)), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; TPred = '$lgt_assertz_rule_checked'(Obj, Clause, This, p(p(_)), p(p(p)), ExCtx),
Clause = (Head :- _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_object'(clause(Head, Body), Obj, TPred, _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'((Head :- Body)) ->
TPred = '$lgt_clause'(Obj, Head, Body, This, p(p(p)), ExCtx)
; '$lgt_check'(clause, (Head :- Body)),
( var(Obj) ->
TPred = '$lgt_clause'(Obj, Head, Body, This, p(p(p)), ExCtx)
; TPred = '$lgt_clause_checked'(Obj, Head, Body, This, p(p(p)), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_object'(retract(Clause), Obj, TPred, _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_retract'(Obj, Clause, This, p(p(p)), ExCtx)
; var(Obj) ->
'$lgt_check'(clause, Clause),
TPred = '$lgt_retract'(Obj, Clause, This, p(p(p)), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( var(Body) ->
TPred = '$lgt_retract_var_body_checked'(Obj, Clause, This, p(p(p)), ExCtx)
; Body == true ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) ->
TPred = retract(THead)
; TPred = '$lgt_retract_fact_checked'(Obj, Head, This, p(p(p)), ExCtx)
)
; TPred = '$lgt_retract_rule_checked'(Obj, Clause, This, p(p(p)), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; TPred = '$lgt_retract_fact_checked'(Obj, Clause, This, p(p(p)), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_object'(retractall(Head), Obj, TPred, _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( var(Head) ->
TPred = '$lgt_retractall'(Obj, Head, This, p(p(p)), ExCtx)
; var(Obj) ->
'$lgt_check'(callable, Head),
TPred = '$lgt_retractall'(Obj, Head, This, p(p(p)), ExCtx)
; '$lgt_check'(callable, Head),
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) ->
TPred = retractall(THead)
; TPred = '$lgt_retractall_checked'(Obj, Head, This, p(p(p)), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
).
% database handling built-in predicates that take a clause reference
% if supported as built-in predicates by the backend Prolog compiler
'$lgt_compile_message_to_object'(assert(Clause, Ref), Obj, TPred, Events, Ctx) :-
'$lgt_prolog_built_in_predicate'(assert(_, _)),
\+ '$lgt_pp_defines_predicate_'(assert(_, _), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, assert/2, assertz/2)
)
; true
),
'$lgt_compile_message_to_object'(assertz(Clause, Ref), Obj, TPred, Events, Ctx).
'$lgt_compile_message_to_object'(asserta(Clause, Ref), Obj, TPred, _, Ctx) :-
'$lgt_prolog_built_in_predicate'(asserta(_, _)),
\+ '$lgt_pp_defines_predicate_'(asserta(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_asserta'(Obj, Clause, Ref, This, p(p(_)), p(p(p)), ExCtx)
; var(Obj) ->
'$lgt_check'(clause, Clause),
TPred = '$lgt_asserta'(Obj, Clause, Ref, This, p(p(_)), p(p(p)), ExCtx)
; '$lgt_check'(clause, Clause),
( (Clause = (Head :- Body) -> Body == true; Clause = Head) ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) ->
TPred = asserta(THead, Ref)
; TPred = '$lgt_asserta_fact_checked'(Obj, Head, Ref, This, p(p(_)), p(p(p)), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; TPred = '$lgt_asserta_rule_checked'(Obj, Clause, Ref, This, p(p(_)), p(p(p)), ExCtx),
Clause = (Head :- _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_object'(assertz(Clause, Ref), Obj, TPred, _, Ctx) :-
'$lgt_prolog_built_in_predicate'(assertz(_, _)),
\+ '$lgt_pp_defines_predicate_'(assertz(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_assertz'(Obj, Clause, Ref, Ref, This, p(p(_)), p(p(p)), ExCtx)
; var(Obj) ->
'$lgt_check'(clause, Clause),
TPred = '$lgt_assertz'(Obj, Clause, Ref, This, p(p(_)), p(p(p)), ExCtx)
; '$lgt_check'(clause, Clause),
( (Clause = (Head :- Body) -> Body == true; Clause = Head) ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) ->
TPred = assertz(THead, Ref)
; TPred = '$lgt_assertz_fact_checked'(Obj, Head, Ref, This, p(p(_)), p(p(p)), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
; TPred = '$lgt_assertz_rule_checked'(Obj, Clause, Ref, This, p(p(_)), p(p(p)), ExCtx),
Clause = (Head :- _),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_object'(clause(Head, Body, Ref), Obj, TPred, _, Ctx) :-
'$lgt_prolog_built_in_predicate'(clause(_, _, _)),
\+ '$lgt_pp_defines_predicate_'(clause(_, _, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _),
( '$lgt_runtime_checked_db_clause'((Head :- Body)) ->
TPred = '$lgt_clause'(Obj, Head, Body, Ref, This, p(p(p)), ExCtx)
; '$lgt_check'(clause, (Head :- Body)),
( var(Obj) ->
TPred = '$lgt_clause'(Obj, Head, Body, Ref, This, p(p(p)), ExCtx)
; TPred = '$lgt_clause_checked'(Obj, Head, Body, Ref, This, p(p(p)), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, Obj::Functor/Arity, CallerHead)
)
).
% term and goal expansion predicates
'$lgt_compile_message_to_object'(expand_term(Term, Expansion), Obj, '$lgt_expand_term_message'(Obj, Term, Expansion, This, p(p(p)), ExCtx), _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _).
'$lgt_compile_message_to_object'(expand_goal(Goal, ExpandedGoal), Obj, '$lgt_expand_goal_message'(Obj, Goal, ExpandedGoal, This, p(p(p))), _, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, This, _).
% compiler bypass control construct
'$lgt_compile_message_to_object'({Goal}, _, call(Goal), _, _) :-
!,
'$lgt_check'(var_or_callable, Goal).
% invalid message
'$lgt_compile_message_to_object'(Pred, _, _, _, _) :-
\+ callable(Pred),
throw(type_error(callable, Pred)).
% message is not a built-in control construct or a call to a built-in (meta-)predicate
'$lgt_compile_message_to_object'(Pred, Obj, TPred, Events, Ctx) :-
var(Obj),
% translation performed at runtime
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_object_message'(Mode, Obj, Pred, Pred, Head),
( Events == allow ->
TPred = '$lgt_send_to_obj'(Obj, Pred, ExCtx)
; TPred = '$lgt_send_to_obj_ne'(Obj, Pred, ExCtx)
).
% special case where an object sends a message to itself; the practical
% case is parametric objects where one of more parameters are updated by
% the object predicates
'$lgt_compile_message_to_object'(Pred, Obj, TPred, Events, Ctx) :-
'$lgt_pp_entity_'(object, Entity, _),
functor(Obj, Functor, Arity),
functor(Entity, Functor, Arity),
'$lgt_pp_defines_predicate_'(Pred, _, _, _, _, _),
% local predicate
!,
'$lgt_comp_ctx'(Ctx, Head, HeadExCtx, Entity, _, This, _, Prefix, MetaVars, _, ExCtx, Mode, _, Lines, Term),
'$lgt_comp_ctx'(NewCtx, Head, HeadExCtx, Obj, Entity, Obj, Obj, Prefix, MetaVars, _, NewExCtx, Mode, _, Lines, Term),
'$lgt_execution_context_this_entity'(ExCtx, This, Entity),
'$lgt_execution_context'(NewExCtx, Obj, This, Obj, Obj, [], []),
'$lgt_compile_body'(Pred, message, TPred0, _, NewCtx),
( Events == allow ->
TPred = '$lgt_guarded_method_call'(Obj, Pred, This, TPred0)
; TPred = TPred0
).
'$lgt_compile_message_to_object'(Pred, Obj, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
% check for a user-defined linter warning
once(logtalk_linter_hook(Obj::Pred, Flag, File, Lines, Type, Entity, Warning)),
nonvar(Flag),
'$lgt_valid_flag'(Flag),
'$lgt_compiler_flag'(Flag, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(Flag), Warning),
fail.
'$lgt_compile_message_to_object'(Pred, Obj, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_current_object_'(Obj, _, Dcl, _, _, _, _, _, _, _, _),
\+ call(Dcl, forward(_), _, _, _, _, _),
\+ call(Dcl, Pred, _, _, _, _, _),
'$lgt_compiler_flag'(unknown_predicates, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_entity_'(Type, Entity, _) ->
Message = message_not_understood(File, Lines, Type, Entity, Obj, Pred)
; Message = message_not_understood(File, Lines, Obj, Pred)
),
'$lgt_print_message'(warning(unknown_predicates), Message),
fail.
'$lgt_compile_message_to_object'(Pred, Obj, TPred, Events, Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, This, _, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_add_referenced_object_message'(Mode, Obj, Pred, Pred, Head),
( Events == allow ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_static_binding'(Obj, Pred, Call, Ctx) ->
'$lgt_execution_context_this_entity'(ExCtx, This, _),
TPred = '$lgt_guarded_method_call'(Obj, Pred, This, Call)
; TPred = '$lgt_send_to_obj_'(Obj, Pred, ExCtx)
)
; ( '$lgt_compiler_flag'(optimize, on),
'$lgt_send_to_obj_static_binding'(Obj, Pred, TPred, Ctx) ->
true
; TPred = '$lgt_send_to_obj_ne_'(Obj, Pred, ExCtx)
)
).
% '$lgt_compile_message_to_self'(@term, -callable, @execution_context)
%
% compiles the sending of a message to self
% translation performed at runtime
'$lgt_compile_message_to_self'(Pred, '$lgt_send_to_self'(Pred, NewCtx), Ctx) :-
var(Pred),
!,
'$lgt_comp_ctx'(Ctx, Head, _, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, _, Stack, Lines, _),
'$lgt_comp_ctx'(NewCtx, Head, _, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, runtime, Stack, Lines, _).
% suspicious use of ::/1 instead of a local predicate call in clauses that
% apparently are meant to implement recursive predicate definitions where
% the user intention is to call the local predicate; the user may also
% intend to make a "super" call instead of a message to "self"
'$lgt_compile_message_to_self'(Pred, _, Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, compile(_,_,_), _, _, _),
'$lgt_compiler_flag'(suspicious_calls, warning),
functor(Pred, Functor, Arity),
functor(Head, Functor, Arity),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(suspicious_calls),
suspicious_call(File, Lines, Type, Entity, ::Pred, [Pred, ^^Pred])
),
fail.
% broadcasting control constructs
'$lgt_compile_message_to_self'((Pred1, Pred2), (TPred1, TPred2), Ctx) :-
!,
'$lgt_compile_message_to_self'(Pred1, TPred1, Ctx),
'$lgt_compile_message_to_self'(Pred2, TPred2, Ctx).
'$lgt_compile_message_to_self'((Pred1; Pred2), (TPred1; TPred2), Ctx) :-
!,
'$lgt_compile_message_to_self'(Pred1, TPred1, Ctx),
'$lgt_compile_message_to_self'(Pred2, TPred2, Ctx).
'$lgt_compile_message_to_self'((Pred1 -> Pred2), (TPred1 -> TPred2), Ctx) :-
!,
'$lgt_compile_message_to_self'(Pred1, TPred1, Ctx),
'$lgt_compile_message_to_self'(Pred2, TPred2, Ctx).
'$lgt_compile_message_to_self'('*->'(Pred1, Pred2), '*->'(TPred1, TPred2), Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_compile_message_to_self'(Pred1, TPred1, Ctx),
'$lgt_compile_message_to_self'(Pred2, TPred2, Ctx).
% built-in methods that cannot be redefined
'$lgt_compile_message_to_self'(!, !, _) :-
!.
'$lgt_compile_message_to_self'(true, true, _) :-
!.
'$lgt_compile_message_to_self'(false, false, _) :-
!.
'$lgt_compile_message_to_self'(fail, fail, _) :-
!.
'$lgt_compile_message_to_self'(repeat, repeat, _) :-
!.
% reflection built-in predicates
'$lgt_compile_message_to_self'(current_op(Priority, Specifier, Operator), '$lgt_current_op'(Self, Priority, Specifier, Operator, This, p(_), ExCtx), Ctx) :-
!,
'$lgt_check'(var_or_operator_priority, Priority),
'$lgt_check'(var_or_operator_specifier, Specifier),
'$lgt_check'(var_or_atom, Operator),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, Self, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _).
'$lgt_compile_message_to_self'(current_predicate(Pred), '$lgt_current_predicate'(Self, Pred, This, p(_), ExCtx), Ctx) :-
!,
'$lgt_check'(var_or_predicate_indicator, Pred),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, Self, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _).
'$lgt_compile_message_to_self'(predicate_property(Pred, Prop), '$lgt_predicate_property'(Self, Pred, Prop, This, p(_), ExCtx), Ctx) :-
!,
'$lgt_check'(var_or_callable, Pred),
'$lgt_check'(var_or_predicate_property, Prop),
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, Self, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _).
% database handling built-in predicates
'$lgt_compile_message_to_self'(abolish(Functor, Arity), TPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(abolish(_, _)),
\+ '$lgt_pp_defines_predicate_'(abolish(_, _), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, abolish/2, abolish/1)
)
; true
),
'$lgt_compile_message_to_self'(abolish(Functor/Arity), TPred, Ctx).
'$lgt_compile_message_to_self'(abolish(Pred), TPred, Ctx) :-
!,
'$lgt_check'(var_or_predicate_indicator, Pred),
'$lgt_comp_ctx'(Ctx, Head, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( ground(Pred) ->
TPred = '$lgt_abolish_checked'(Self, Pred, This, p(_), ExCtx),
'$lgt_remember_updated_predicate'(Mode, ::Pred, Head)
; % partially instantiated predicate indicator; runtime check required
TPred = '$lgt_abolish'(Self, Pred, This, p(_), ExCtx)
).
'$lgt_compile_message_to_self'(assert(Clause), TPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(assert(_)),
\+ '$lgt_pp_defines_predicate_'(assert(_), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, assert/1, assertz/1)
)
; true
),
'$lgt_compile_message_to_self'(assertz(Clause), TPred, Ctx).
'$lgt_compile_message_to_self'(asserta(Clause), TPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_asserta'(Self, Clause, This, p(_), p(p), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TPred = '$lgt_asserta_fact_checked'(Self, Head, This, p(_), p(p), ExCtx)
; TPred = '$lgt_asserta_rule_checked'(Self, Clause, This, p(_), p(p), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
; TPred = '$lgt_asserta_fact_checked'(Self, Clause, This, p(_), p(p), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_self'(assertz(Clause), TPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_assertz'(Self, Clause, This, p(_), p(p), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TPred = '$lgt_assertz_fact_checked'(Self, Head, This, p(_), p(p), ExCtx)
; TPred = '$lgt_assertz_rule_checked'(Self, Clause, This, p(_), p(p), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
; TPred = '$lgt_assertz_fact_checked'(Self, Clause, This, p(_), p(p), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_self'(clause(Head, Body), TPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'((Head :- Body)) ->
TPred = '$lgt_clause'(Self, Head, Body, This, p(_), ExCtx)
; '$lgt_check'(clause, (Head :- Body)),
TPred = '$lgt_clause_checked'(Self, Head, Body, This, p(_), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
).
'$lgt_compile_message_to_self'(retract(Clause), TPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_retract'(Self, Clause, This, p(_), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( var(Body) ->
TPred = '$lgt_retract_var_body_checked'(Self, Clause, This, p(_), ExCtx)
; Body == true ->
TPred = '$lgt_retract_fact_checked'(Self, Head, This, p(_), ExCtx)
; TPred = '$lgt_retract_rule_checked'(Self, Clause, This, p(_), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
; TPred = '$lgt_retract_fact_checked'(Self, Clause, This, p(_), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_self'(retractall(Head), TPred, Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( var(Head) ->
TPred = '$lgt_retractall'(Self, Head, This, p(_), ExCtx)
; '$lgt_check'(callable, Head),
TPred = '$lgt_retractall_checked'(Self, Head, This, p(_), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
).
% database handling built-in predicates that take a clause reference
% if supported as built-in predicates by the backend Prolog compiler
'$lgt_compile_message_to_self'(assert(Clause, Ref), TPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(assert(_, _)),
\+ '$lgt_pp_defines_predicate_'(assert(_, _), _, _, _, _, _),
!,
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(deprecated, warning),
'$lgt_source_file_context'(File, Lines),
'$lgt_pp_entity_'(Type, Entity, _) ->
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(deprecated),
deprecated_predicate(File, Lines, Type, Entity, assert/2, assertz/2)
)
; true
),
'$lgt_compile_message_to_self'(assertz(Clause, Ref), TPred, Ctx).
'$lgt_compile_message_to_self'(asserta(Clause, Ref), TPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(asserta(_, _)),
\+ '$lgt_pp_defines_predicate_'(asserta(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_asserta'(Self, Clause, Ref, This, p(_), p(p), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TPred = '$lgt_asserta_fact_checked'(Self, Head, Ref, This, p(_), p(p), ExCtx)
; TPred = '$lgt_asserta_rule_checked'(Self, Clause, Ref, This, p(_), p(p), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
; TPred = '$lgt_asserta_fact_checked'(Self, Clause, Ref, This, p(_), p(p), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_self'(assertz(Clause, Ref), TPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(assertz(_, _)),
\+ '$lgt_pp_defines_predicate_'(assertz(_, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'(Clause) ->
TPred = '$lgt_assertz'(Self, Clause, Ref, This, p(_), p(p), ExCtx)
; '$lgt_check'(clause, Clause),
( Clause = (Head :- Body) ->
( Body == true ->
TPred = '$lgt_assertz_fact_checked'(Self, Head, Ref, This, p(_), p(p), ExCtx)
; TPred = '$lgt_assertz_rule_checked'(Self, Clause, Ref, This, p(_), p(p), ExCtx)
),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
; TPred = '$lgt_assertz_fact_checked'(Self, Clause, Ref, This, p(_), p(p), ExCtx),
functor(Clause, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
)
).
'$lgt_compile_message_to_self'(clause(Head, Body, Ref), TPred, Ctx) :-
'$lgt_prolog_built_in_predicate'(clause(_, _, _)),
\+ '$lgt_pp_defines_predicate_'(clause(_, _, _), _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, CallerHead, _, _, _, This, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
( '$lgt_runtime_checked_db_clause'((Head :- Body)) ->
TPred = '$lgt_clause'(Self, Head, Body, Ref, This, p(_), ExCtx)
; '$lgt_check'(clause, (Head :- Body)),
TPred = '$lgt_clause_checked'(Self, Head, Body, Ref, This, p(_), ExCtx),
functor(Head, Functor, Arity),
'$lgt_remember_updated_predicate'(Mode, ::Functor/Arity, CallerHead)
).
% term and goal expansion predicates
'$lgt_compile_message_to_self'(expand_term(Term, Expansion), '$lgt_expand_term_message'(Self, Term, Expansion, This, p(_), ExCtx), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, Self, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _).
'$lgt_compile_message_to_self'(expand_goal(Goal, ExpandedGoal), '$lgt_expand_goal_message'(Self, Goal, ExpandedGoal, This, p(_)), Ctx) :-
!,
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, Self, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _).
% compiler bypass control construct
'$lgt_compile_message_to_self'({Goal}, call(Goal), _) :-
!,
'$lgt_check'(var_or_callable, Goal).
% invalid message
'$lgt_compile_message_to_self'(Pred, _, _) :-
\+ callable(Pred),
throw(type_error(callable, Pred)).
% message is not a built-in control construct or a call to a built-in
% (meta-)predicate: translation performed at runtime
'$lgt_compile_message_to_self'(Pred, '$lgt_send_to_self_'(Self, Pred, ExCtx), Ctx) :-
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, Self, _, _, _, ExCtx, Mode, _, _, _),
'$lgt_execution_context'(ExCtx, _, _, _, Self, _, _),
functor(Pred, Functor, Arity),
'$lgt_remember_called_self_predicate'(Mode, Functor/Arity, Head),
!.
% '$lgt_compile_super_call'(@term, -callable, +compilation_context)
%
% compiles calling of redefined predicates ("super" calls)
'$lgt_compile_super_call'(Pred, TPred, Ctx) :-
'$lgt_pp_object_'(Obj, _, _, _, Super, _, _, _, _, _, _),
!,
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
( \+ '$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _),
\+ '$lgt_pp_imported_category_'(_, _, _, _, _, _) ->
% invalid goal (no ancestor entity)
throw(existence_error(ancestor, object))
; var(Pred) ->
% translation performed at runtime
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_obj_super_call'(Super, Pred, ExCtx)
; callable(Pred) ->
( '$lgt_compiler_flag'(optimize, on),
'$lgt_obj_related_entities_are_static',
'$lgt_obj_super_call_static_binding'(Obj, Pred, ExCtx, TPred) ->
true
; TPred = '$lgt_obj_super_call_'(Super, Pred, ExCtx)
),
functor(Pred, Functor, Arity),
'$lgt_remember_called_super_predicate'(Mode, Functor/Arity, Head)
; throw(type_error(callable, Pred))
).
'$lgt_compile_super_call'(Pred, TPred, Ctx) :-
'$lgt_pp_complemented_object_'(Obj, _, _, _, _),
% super calls from predicates defined in complementing categories
% lookup inherited definitions in the complemented object ancestors
!,
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
( var(Pred) ->
TPred = (
'$lgt_current_object_'(Obj, _, _, _, Super, _, _, _, _, _, _),
'$lgt_obj_super_call'(Super, Pred, ExCtx)
)
; callable(Pred) ->
TPred = (
'$lgt_current_object_'(Obj, _, _, _, Super, _, _, _, _, _, _),
'$lgt_obj_super_call_'(Super, Pred, ExCtx)
)
; throw(type_error(callable, Pred))
).
'$lgt_compile_super_call'(Pred, TPred, Ctx) :-
'$lgt_pp_category_'(Ctg, _, _, _, _, _),
!,
( \+ '$lgt_pp_extended_category_'(_, _, _, _, _, _) ->
% invalid goal (not an extended category)
throw(existence_error(ancestor, category))
; var(Pred) ->
% translation performed at runtime
'$lgt_comp_ctx_exec_ctx'(Ctx, ExCtx),
TPred = '$lgt_ctg_super_call'(Ctg, Pred, ExCtx)
; callable(Pred) ->
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, ExCtx, Mode, _, _, _),
( '$lgt_compiler_flag'(optimize, on),
'$lgt_ctg_related_entities_are_static',
'$lgt_ctg_super_call_static_binding'(Ctg, Pred, ExCtx, TPred) ->
true
; TPred = '$lgt_ctg_super_call_'(Ctg, Pred, ExCtx)
),
functor(Pred, Functor, Arity),
'$lgt_remember_called_super_predicate'(Mode, Functor/Arity, Head)
; throw(type_error(callable, Pred))
).
'$lgt_compile_super_call'(Pred, TPred, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, ExCtx, runtime, _, _, _),
callable(This),
'$lgt_current_object_'(This, _, _, _, Super, _, _, _, _, _, _),
TPred = '$lgt_obj_super_call'(Super, Pred, ExCtx).
'$lgt_obj_related_entities_are_static' :-
forall(
'$lgt_pp_extended_object_'(Obj, _, _, _, _, _, _, _, _, _, _),
('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags), Flags /\ 2 =:= 0)
),
forall(
'$lgt_pp_instantiated_class_'(Obj, _, _, _, _, _, _, _, _, _, _),
('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags), Flags /\ 2 =:= 0)
),
forall(
'$lgt_pp_specialized_class_'(Obj, _, _, _, _, _, _, _, _, _, _),
('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags), Flags /\ 2 =:= 0)
),
forall(
'$lgt_pp_imported_category_'(Ctg, _, _, _, _, _),
('$lgt_current_category_'(Ctg, _, _, _, _, Flags), Flags /\ 2 =:= 0)
),
forall(
'$lgt_pp_implemented_protocol_'(Ptc, _, _, _, _),
('$lgt_current_protocol_'(Ptc, _, _, _, Flags), Flags /\ 2 =:= 0)
).
'$lgt_ctg_related_entities_are_static' :-
forall(
'$lgt_pp_extended_category_'(Ctg, _, _, _, _, _),
('$lgt_current_category_'(Ctg, _, _, _, _, Flags), Flags /\ 2 =:= 0)
),
forall(
'$lgt_pp_implemented_protocol_'(Ptc, _, _, _, _),
('$lgt_current_protocol_'(Ptc, _, _, _, Flags), Flags /\ 2 =:= 0)
).
% '$lgt_compile_context_switch_call'(@term, @term, -callable, @execution_context)
%
% compiles context switching calls
'$lgt_compile_context_switch_call'(Obj, Goal, TGoal, ExCtx) :-
( var(Obj) ->
'$lgt_check'(var_or_callable, Goal),
TGoal = '$lgt_call_within_context'(Obj, Goal, ExCtx)
; Obj = {Proxy} ->
'$lgt_check'(var_or_callable, Proxy),
( var(Proxy) ->
CallProxy = call(Proxy)
; CallProxy = Proxy
),
'$lgt_compile_context_switch_call'(Proxy, Goal, TGoal0, ExCtx),
TGoal = (CallProxy, TGoal0)
; var(Goal) ->
'$lgt_check'(var_or_object_identifier, Obj),
TGoal = '$lgt_call_within_context'(Obj, Goal, ExCtx)
; '$lgt_check'(object_identifier, Obj),
'$lgt_check'(callable, Goal),
TGoal = '$lgt_call_within_context_nv'(Obj, Goal, ExCtx)
).
% '$lgt_head_meta_variables'(+callable, -list(variable))
%
% constructs a list of all variables that occur in a position corresponding
% to a meta-argument in the head of clause being compiled
'$lgt_head_meta_variables'(Head, MetaVars) :-
( '$lgt_find_head_meta_predicate_template'(Head, Pred, Template) ->
Pred =.. [_| Args],
Template =.. [_| MArgs],
'$lgt_extract_meta_variables'(Args, MArgs, MetaVars)
; MetaVars = []
).
'$lgt_find_head_meta_predicate_template'(Entity::Pred, Pred, Template) :-
( '$lgt_pp_meta_predicate_'(Entity::Pred, Entity::Template, _, _)
; '$lgt_current_object_'(Entity, _, Dcl, _, _, _, _, _, _, _, _),
call(Dcl, Pred, _, Template, _), Template \== no
; '$lgt_current_category_'(Entity, _, Dcl, _, _, _),
call(Dcl, Pred, _, Template, _), Template \== no
),
!.
'$lgt_find_head_meta_predicate_template'(':'(Module, Pred), Pred, Template) :-
'$lgt_pp_meta_predicate_'(':'(Module, Pred), ':'(Module, Template), _, _),
!.
'$lgt_find_head_meta_predicate_template'(Head, Head, Meta) :-
'$lgt_pp_meta_predicate_'(Head, Meta, _, _).
'$lgt_extract_meta_variables'([], [], []).
'$lgt_extract_meta_variables'([Arg| Args], [MArg| MArgs], MetaVars) :-
( MArg == (*) ->
% normal argument
'$lgt_extract_meta_variables'(Args, MArgs, MetaVars)
; MArg == (::) ->
term_variables(Arg, MetaVars0),
'$lgt_append'(MetaVars0, MetaVars1, MetaVars),
'$lgt_extract_meta_variables'(Args, MArgs, MetaVars1)
; integer(MArg),
% meta-argument (closure or goal)
nonvar(Arg) ->
throw(type_error(variable, Arg))
; var(Arg) ->
% meta-argument
MetaVars = [Arg| RestMetaVars],
'$lgt_extract_meta_variables'(Args, MArgs, RestMetaVars)
; % bound argument and thus not a meta-variable
'$lgt_extract_meta_variables'(Args, MArgs, MetaVars)
).
% '$lgt_goal_meta_arguments'(+callable, +callable, -list(term))
%
% constructs a list of all meta-arguments in a goal
'$lgt_goal_meta_arguments'(no, _, []) :-
!.
'$lgt_goal_meta_arguments'(Meta, Goal, MetaArgs) :-
% don't require the same predicate name for the meta-predicate
% template and the goal as the goal may be an alias
Meta =.. [_| MArgs],
Goal =.. [_| Args],
'$lgt_extract_meta_arguments'(MArgs, Args, MetaArgs).
'$lgt_extract_meta_arguments'([], [], []).
'$lgt_extract_meta_arguments'([MArg| MArgs], [Arg| Args], MetaArgs) :-
( MArg == (*) ->
% normal argument
'$lgt_extract_meta_arguments'(MArgs, Args, MetaArgs)
; % meta-argument
MetaArgs = [Arg| RestMetaArgs],
'$lgt_extract_meta_arguments'(MArgs, Args, RestMetaArgs)
).
% '$lgt_goal_meta_call_context'(+callable, @term, @term, -callable)
%
% returns the meta-call execution context: an empty list for local
% meta-calls or the sender execution context when the message is for
% a meta-predicate
'$lgt_goal_meta_call_context'(no, ExCtx, This, []) :-
!,
'$lgt_execution_context_this_entity'(ExCtx, This, _).
'$lgt_goal_meta_call_context'(_, ExCtx, This, ExCtx) :-
'$lgt_execution_context_this_entity'(ExCtx, This, _).
% '$lgt_iso_read_term'(@stream, ?term, +read_options_list, @list)
%
% wraps read_term/3 call with the necessary operator settings
'$lgt_iso_read_term'(Stream, Term, Options, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
read_term(Stream, Term, Options),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_read_term'(?term, +read_options_list, @list)
%
% wraps read_term/2 call with the necessary operator settings
'$lgt_iso_read_term'(Term, Options, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
read_term(Term, Options),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_read'(@stream, ?term, @list)
%
% wraps read/2 call with the necessary operator settings
'$lgt_iso_read'(Stream, Term, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
read(Stream, Term),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_read'(?term, @list)
%
% wraps read/1 call with the necessary operator settings
'$lgt_iso_read'(Term, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
read(Term),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_write_term'(@stream_or_alias, @term, @write_options_list, @list)
%
% wraps write_term/3 call with the necessary operator settings
'$lgt_iso_write_term'(Stream, Term, Options, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
write_term(Stream, Term, Options),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_write_term'(@term, @write_options_list, @list)
%
% wraps write_term/2 call with the necessary operator settings
'$lgt_iso_write_term'(Term, Options, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
write_term(Term, Options),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_write'(@stream_or_alias, @term, @list)
%
% wraps write/2 call with the necessary operator settings
'$lgt_iso_write'(Stream, Term, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
write(Stream, Term),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_write'(@term, @list)
%
% wraps write/1 call with the necessary operator settings
'$lgt_iso_write'(Term, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
write(Term),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_writeq'(@stream_or_alias, @term, @list)
%
% wraps writeq/2 call with the necessary operator settings
'$lgt_iso_writeq'(Stream, Term, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
writeq(Stream, Term),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_iso_writeq'(@term, @list)
%
% wraps writeq/1 call with the necessary operator settings
'$lgt_iso_writeq'(Term, Operators) :-
catch(
( '$lgt_save_operators'(Operators, Saved),
'$lgt_add_operators'(Operators),
writeq(Term),
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved)
),
Error,
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error)
).
% '$lgt_save_operators'(@list, -list)
%
% saves currently defined operators that might be
% redefined when a list of operators is added
'$lgt_save_operators'([], []).
'$lgt_save_operators'([op(_, Specifier, Operator)| Operators], Saved) :-
( current_op(Priority, SCSpecifier, Operator),
'$lgt_same_operator_class'(Specifier, SCSpecifier) ->
Saved = [op(Priority, SCSpecifier, Operator)| Saved2]
; Saved = Saved2
),
'$lgt_save_operators'(Operators, Saved2).
% '$lgt_add_operators'(@list)
%
% adds operators to the global operator table
'$lgt_add_operators'([]).
'$lgt_add_operators'([op(Priority, Specifier, Operator)| Operators]) :-
op(Priority, Specifier, Operator),
'$lgt_add_operators'(Operators).
% '$lgt_remove_operators'(@list)
%
% removes operators from the global operator table
'$lgt_remove_operators'([]).
'$lgt_remove_operators'([op(_, Specifier, Operator)| Operators]) :-
op(0, Specifier, Operator),
'$lgt_remove_operators'(Operators).
% '$lgt_iso_stream_input_output_error_handler'(@list, @list, @nonvar)
%
% restores operator table to its state before the call
% to one of the '$lgt_iso_read...' that raised an error
'$lgt_iso_stream_input_output_error_handler'(Operators, Saved, Error) :-
'$lgt_remove_operators'(Operators),
'$lgt_add_operators'(Saved),
throw(Error).
% '$lgt_simplify_goal'(+callable, -callable)
%
% simplify the body of a compiled clause by folding left unifications (usually
% resulting from the compilation of grammar rules or from inlined calls to the
% execution-context built-in methods) and by removing redundant calls to true/0
% (but we must be careful with control constructs that are opaque to cuts such
% as call/1 and once/1)
'$lgt_simplify_goal'(Goal, SGoal) :-
'$lgt_flatten_conjunctions'(Goal, SGoal0),
'$lgt_fold_left_unifications'(SGoal0, SGoal1),
'$lgt_remove_redundant_calls'(SGoal1, SGoal).
% '$lgt_flatten_conjunctions'(+callable, -callable)
%
% flattens conjunction of goals
%
% only standard or de facto standard control constructs are traversed to avoid
% compiler performance penalties
'$lgt_flatten_conjunctions'(Goal, Goal) :-
var(Goal),
!.
'$lgt_flatten_conjunctions'('*->'(Goal1, Goal2), '*->'(SGoal1, SGoal2)) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_flatten_conjunctions'(Goal1, SGoal1),
'$lgt_flatten_conjunctions'(Goal2, SGoal2).
'$lgt_flatten_conjunctions'((Goal1 -> Goal2), (SGoal1 -> SGoal2)) :-
!,
'$lgt_flatten_conjunctions'(Goal1, SGoal1),
'$lgt_flatten_conjunctions'(Goal2, SGoal2).
'$lgt_flatten_conjunctions'((Goal1; Goal2), (SGoal1; SGoal2)) :-
!,
'$lgt_flatten_conjunctions'(Goal1, SGoal1),
'$lgt_flatten_conjunctions'(Goal2, SGoal2).
'$lgt_flatten_conjunctions'((Goal1, Goal2), (Goal1, SGoal2)) :-
var(Goal1),
!,
'$lgt_flatten_conjunctions'(Goal2, SGoal2).
'$lgt_flatten_conjunctions'(((Goal1, Goal2), Goal3), Body) :-
!,
'$lgt_flatten_conjunctions'((Goal1, (Goal2, Goal3)), Body).
'$lgt_flatten_conjunctions'((Goal1, Goal2), (Goal1, Goal3)) :-
!,
'$lgt_flatten_conjunctions'(Goal2, Goal3).
'$lgt_flatten_conjunctions'(\+ Goal, \+ SGoal) :-
!,
'$lgt_flatten_conjunctions'(Goal, SGoal).
'$lgt_flatten_conjunctions'(Goal, Goal).
% '$lgt_fold_left_unifications'(+goal, -goal)
%
% folds left unifications; right unifications cannot be folded otherwise
% we may loose steadfastness; the left unifications are typically produced
% when compiling grammar rules to clauses
%
% as the clauses containing the goals being simplified will be asserted
% between the compiler stages, we must be careful to not create cyclic
% terms when performing term unification
'$lgt_fold_left_unifications'(Goal, Goal) :-
var(Goal),
!.
'$lgt_fold_left_unifications'((Term1 = Term2), true) :-
unify_with_occurs_check(Term1, Term2),
!.
'$lgt_fold_left_unifications'(((Term1 = Term2), Goal), Folded) :-
unify_with_occurs_check(Term1, Term2),
!,
'$lgt_fold_left_unifications'(Goal, Folded).
'$lgt_fold_left_unifications'(Goal, Goal).
% '$lgt_remove_redundant_calls'(+callable, -callable)
%
% removes redundant calls to true/0 from a compiled clause body (we must
% be careful with control constructs that are opaque to cuts such as call/1
% and once/1) and folds pairs of consecutive variable unifications
% (Var1 = Var2, Var2 = Var3) that are usually generated as a by-product of
% the compilation of grammar rules; only standard or de facto standard control
% constructs and meta-predicates are traversed
'$lgt_remove_redundant_calls'(Goal, Goal) :-
var(Goal),
!.
'$lgt_remove_redundant_calls'(catch(Goal0, Error, Goal2), SGoal) :-
nonvar(Goal0),
Goal0 = call(Goal1),
!,
'$lgt_remove_redundant_calls'(catch(Goal1, Error, Goal2), SGoal).
'$lgt_remove_redundant_calls'(catch(Goal1, Error, Goal2), catch(SGoal1, Error, SGoal2)) :-
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal1),
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'(call(Goal), true) :-
Goal == !,
!.
'$lgt_remove_redundant_calls'(call(Goal), SGoal) :-
callable(Goal),
functor(Goal, Functor, _),
sub_atom(Functor, 0, _, _, '$lgt_'), % e.g. '$lgt_metacall'
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(call(Goal), call(SGoal)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(once(Goal), true) :-
Goal == !,
!.
'$lgt_remove_redundant_calls'(once(Goal), once(SGoal)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(ignore(Goal), ignore(SGoal)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(bagof(Term, Goal, List), bagof(Term, SGoal, List)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(setof(Term, Goal, List), setof(Term, SGoal, List)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(findall(Term, Goal, List), findall(Term, SGoal, List)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(findall(Term, Goal, List, Tail), findall(Term, SGoal, List, Tail)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(forall(Goal1, Goal2), forall(SGoal1, SGoal2)) :-
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal1),
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'((IfThen; Else), (SIf -> SThen; SElse)) :-
nonvar(IfThen),
IfThen = (If -> Then),
!,
'$lgt_remove_redundant_calls'(If, SIf),
'$lgt_remove_redundant_calls'(Then, SThen),
'$lgt_remove_redundant_calls'(Else, SElse).
'$lgt_remove_redundant_calls'((IfThen; Else), ('*->'(SIf, SThen); SElse)) :-
nonvar(IfThen),
IfThen = '*->'(If, Then),
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_remove_redundant_calls'(If, SIf),
'$lgt_remove_redundant_calls'(Then, SThen),
'$lgt_remove_redundant_calls'(Else, SElse).
'$lgt_remove_redundant_calls'((Goal1; Goal2), (SGoal1; SGoal2)) :-
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal10),
'$lgt_fix_disjunction_left_side'(SGoal10, SGoal1),
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'((Goal1 -> Goal2), (SGoal1 -> SGoal2)) :-
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal1),
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'('*->'(Goal1, Goal2), '*->'(SGoal1, SGoal2)) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal1),
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'((Goal1, Goal2), (Goal1, SGoal2)) :-
var(Goal1),
!,
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'((Goal1, Goal2), (SGoal1, Goal2)) :-
var(Goal2),
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal1).
'$lgt_remove_redundant_calls'((Var1 = Var2a, Var2b = Var3, Goal), SGoal) :-
Var2a == Var2b,
'$lgt_remove_redundant_calls'((Var1 = Var3, Goal), SGoal),
!.
'$lgt_remove_redundant_calls'((Var1 = Var2a, Var2b = Var3), (Var1 = Var3)) :-
Var2a == Var2b,
!.
'$lgt_remove_redundant_calls'((Var1 = Var2, Goal), (Var1 = Var2, SGoal)) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'((true, Goal), SGoal) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'((Goal, true), SGoal) :-
% make sure that we don't arrive here while simplifying a (((If->Then),true);Goal) goal (or a
% as (((If*->Then),true);Goal) goal) as removing the call to true/0 would wrongly convert the
% disjunction into an if-then-else goal (or a soft-cut goal with an else part)
Goal \= (_ -> _),
( '$lgt_predicate_property'('*->'(_, _), built_in) ->
Goal \= '*->'(_, _)
; true
),
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'((Goal1, Goal2), (SGoal1, SGoal2)) :-
!,
'$lgt_remove_redundant_calls'(Goal1, SGoal1),
'$lgt_remove_redundant_calls'(Goal2, SGoal2).
'$lgt_remove_redundant_calls'(\+ Goal, \+ SGoal) :-
!,
'$lgt_remove_redundant_calls'(Goal, SGoal).
'$lgt_remove_redundant_calls'(Goal, Goal).
% '$lgt_save_parameter_variables'(@object_identifier)
% '$lgt_save_parameter_variables'(@category_identifier)
%
% saves the parameter variable names and positions found
% in parametric entity identifiers for later processing
'$lgt_save_parameter_variables'(Entity) :-
atom(Entity),
% non-parametric entity
!.
'$lgt_save_parameter_variables'(Entity) :-
% all parameters must be variables
Entity =.. [_| Parameters],
'$lgt_member'(Parameter, Parameters),
nonvar(Parameter),
throw(type_error(variable, Parameter)).
'$lgt_save_parameter_variables'(_) :-
'$lgt_pp_term_source_data_'(_, VariableNames, _, _, _),
'$lgt_parameter_variable_pairs'(VariableNames, 1, ParameterVariablePairs),
ParameterVariablePairs \== [],
!,
% only save a non-empty list of parameter
% variables to improve compiler performance
assertz('$lgt_pp_parameter_variables_'(ParameterVariablePairs)).
'$lgt_save_parameter_variables'(_).
'$lgt_parameter_variable_pairs'([], _, []).
'$lgt_parameter_variable_pairs'([VariableName=_| VariableNames], Position, [VariableName-Position| ParameterVariablePairs]) :-
'$lgt_parameter_variable_name'(VariableName),
!,
NextPosition is Position + 1,
'$lgt_parameter_variable_pairs'(VariableNames, NextPosition, ParameterVariablePairs).
'$lgt_parameter_variable_pairs'([_| VariableNames], Position, ParameterVariablePairs) :-
NextPosition is Position + 1,
'$lgt_parameter_variable_pairs'(VariableNames, NextPosition, ParameterVariablePairs).
% '$lgt_parameter_variable_name'(+atom)
%
% checks if a variable name is a parameter variable name (i.e. if the variable
% name starts and ends with an underscore and have at least three characters)
'$lgt_parameter_variable_name'(VariableName) :-
sub_atom(VariableName, Before, 1, 0, '_'),
Before >= 2,
sub_atom(VariableName, 0, 1, _, '_').
% '$lgt_unify_parameter_variables'(+callable, +compilation_context)
%
% unifies any parameter variables found in a parametric entity term
% with the corresponding entity parameters
'$lgt_unify_parameter_variables'(Term, Ctx) :-
'$lgt_pp_parameter_variables_'(ParameterVariables),
'$lgt_pp_term_source_data_'(Term, VariableNames, _, _, _),
VariableNames \== [],
( '$lgt_pp_entity_'(_, Entity, _) ->
% compile time; instantiate the Entity argument in the compilation context
true
; % runtime <2 call; Entity already instantiated in the compilation context
true
),
'$lgt_comp_ctx'(Ctx, _, _, Entity, _, _, _, _, _, _, ExCtx, _, _, _, _),
'$lgt_execution_context_this_entity'(ExCtx, _, Entity),
'$lgt_unify_parameter_variables'(VariableNames, ParameterVariables, Entity, Unified),
% ensure that the compilation context is only further instantiated when the
% term contains at least a parameter variable that is successfully unified
Unified == true,
!.
'$lgt_unify_parameter_variables'(_, _).
'$lgt_unify_parameter_variables'([], _, _, _).
'$lgt_unify_parameter_variables'([VariableName=Variable| VariableNames], ParameterVariables, Entity, true) :-
'$lgt_member'(VariableName-Position, ParameterVariables),
!,
arg(Position, Entity, Variable),
'$lgt_unify_parameter_variables'(VariableNames, ParameterVariables, Entity, true).
'$lgt_unify_parameter_variables'([_| VariableNames], ParameterVariables, Entity, Unified) :-
'$lgt_unify_parameter_variables'(VariableNames, ParameterVariables, Entity, Unified).
% '$lgt_compile_object_identifier'(@object_identifier, @compilation_context)
%
% from the object identifier construct the set of
% functor prefixes used in the compiled code clauses
'$lgt_compile_object_identifier'(Obj, Ctx) :-
( atom(Obj) ->
GObj = Obj
; % parametric object
'$lgt_term_template'(Obj, GObj)
),
'$lgt_add_referenced_object'(GObj, Ctx),
( '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_construct_ic_functors'(GObj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm)
; '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_construct_ic_functors'(GObj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm)
; '$lgt_construct_prototype_functors'(GObj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm)
),
% the object flags are only computed at the end of the entity compilation
assertz('$lgt_pp_object_'(GObj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, _)),
% provide quick access to some common used data on the entity being compiled
assertz('$lgt_pp_entity_'(object, Obj, Prefix)),
% initialize the predicate mutex counter
asserta('$lgt_pp_predicate_mutex_counter_'(0)).
% '$lgt_compile_category_identifier'(@category_identifier, @compilation_context)
%
% from the category identifier construct the set of
% functor prefixes used in the compiled code clauses
'$lgt_compile_category_identifier'(Ctg, Ctx) :-
( atom(Ctg) ->
GCtg = Ctg
; % parametric category
'$lgt_term_template'(Ctg, GCtg)
),
'$lgt_add_referenced_category'(GCtg, Ctx),
'$lgt_construct_category_functors'(GCtg, Prefix, Dcl, Def, Rnm),
% the category flags are only computed at the end of the entity compilation
assertz('$lgt_pp_category_'(GCtg, Prefix, Dcl, Def, Rnm, _)),
% provide quick access to some common used data on the entity being compiled
assertz('$lgt_pp_entity_'(category, Ctg, Prefix)),
% initialize the predicate mutex counter
asserta('$lgt_pp_predicate_mutex_counter_'(0)).
% '$lgt_compile_protocol_identifier'(@protocol_identifier, @compilation_context)
%
% from the protocol identifier construct the set of
% functor prefixes used in the compiled code clauses
'$lgt_compile_protocol_identifier'(Ptc, Ctx) :-
'$lgt_add_referenced_protocol'(Ptc, Ctx),
'$lgt_construct_protocol_functors'(Ptc, Prefix, Dcl, Rnm),
% the protocol flags are only computed at the end of the entity compilation
assertz('$lgt_pp_protocol_'(Ptc, Prefix, Dcl, Rnm, _)),
% provide quick access to some common used data on the entity being compiled
assertz('$lgt_pp_entity_'(protocol, Ptc, Prefix)),
% initialize the predicate mutex counter; necessary in order to be able to
% save synchronized predicate properties
asserta('$lgt_pp_predicate_mutex_counter_'(0)).
% '$lgt_compile_implements_protocol_relation('+list, @object_identifier, @compilation_context)
% '$lgt_compile_implements_protocol_relation'(+list, @category_identifier, @compilation_context)
%
% compiles an "implements" relation between a category or an object and a list of protocols
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_implements_protocol_relation'([Ref| Refs], ObjOrCtg, Ctx) :-
'$lgt_check_entity_reference'(protocol, Ref, Scope, Ptc),
( ObjOrCtg == Ptc ->
throw(permission_error(implement, self, ObjOrCtg))
; '$lgt_is_object'(Ptc) ->
throw(type_error(protocol, Ptc))
; '$lgt_is_category'(Ptc) ->
throw(type_error(protocol, Ptc))
; '$lgt_add_referenced_protocol'(Ptc, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_implements_protocol_'(ObjOrCtg, Ptc, Scope))),
'$lgt_construct_protocol_functors'(Ptc, Prefix, Dcl, _),
assertz('$lgt_pp_implemented_protocol_'(Ptc, ObjOrCtg, Prefix, Dcl, Scope)),
'$lgt_compile_implements_protocol_relation'(Refs, ObjOrCtg, Ctx)
).
'$lgt_compile_implements_protocol_relation'([], _, _).
% '$lgt_compile_imports_category_relation'(+list, @object_identifier, @compilation_context)
%
% compiles an "imports" relation between an object and a list of categories
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_imports_category_relation'([Ref| Refs], Obj, Ctx) :-
'$lgt_check_entity_reference'(category, Ref, Scope, Ctg),
( '$lgt_term_template'(Obj, Ctg) ->
throw(permission_error(import, self, Obj))
; '$lgt_is_object'(Ctg) ->
throw(type_error(category, Ctg))
; '$lgt_is_protocol'(Ctg) ->
throw(type_error(category, Ctg))
; '$lgt_add_referenced_category'(Ctg, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_imports_category_'(Obj, Ctg, Scope))),
'$lgt_construct_category_functors'(Ctg, Prefix, Dcl, Def, _),
assertz('$lgt_pp_imported_category_'(Ctg, Obj, Prefix, Dcl, Def, Scope)),
'$lgt_compile_imports_category_relation'(Refs, Obj, Ctx)
).
'$lgt_compile_imports_category_relation'([], _, _).
% '$lgt_compile_instantiates_class_relation'(+list, @object_identifier, @compilation_context)
%
% compiles an "instantiates" relation between an instance and a list of classes
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_instantiates_class_relation'([Ref| Refs], Obj, Ctx) :-
'$lgt_check_entity_reference'(object, Ref, Scope, Class),
( '$lgt_is_protocol'(Class) ->
throw(type_error(object, Class))
; '$lgt_is_category'(Class) ->
throw(type_error(object, Class))
; '$lgt_is_prototype'(Class) ->
throw(domain_error(class, Class))
; '$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
throw(permission_error(instantiate, class, Class))
; '$lgt_add_referenced_object'(Class, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(Obj, Class, Scope))),
'$lgt_construct_ic_functors'(Class, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, _),
assertz('$lgt_pp_instantiated_class_'(Class, Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Scope)),
'$lgt_compile_instantiates_class_relation'(Refs, Obj, Ctx)
).
'$lgt_compile_instantiates_class_relation'([], _, _).
% '$lgt_compile_specializes_class_relation'(+list, @object_identifier, @compilation_context)
%
% compiles a "specializes" relation between a class and a list of superclasses
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_specializes_class_relation'([Ref| Refs], Class, Ctx) :-
'$lgt_check_entity_reference'(object, Ref, Scope, Superclass),
( '$lgt_term_template'(Class, Superclass) ->
throw(permission_error(specialize, self, Class))
; '$lgt_is_protocol'(Superclass) ->
throw(type_error(object, Superclass))
; '$lgt_is_category'(Superclass) ->
throw(type_error(object, Superclass))
; '$lgt_is_prototype'(Superclass) ->
throw(domain_error(class, Superclass))
; '$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
throw(permission_error(specialize, class, Superclass))
; '$lgt_add_referenced_object'(Superclass, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(Class, Superclass, Scope))),
'$lgt_construct_ic_functors'(Superclass, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, _),
assertz('$lgt_pp_specialized_class_'(Superclass, Class, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Scope)),
'$lgt_compile_specializes_class_relation'(Refs, Class, Ctx)
).
'$lgt_compile_specializes_class_relation'([], _, _).
% '$lgt_compile_extends_object_relation'(+list, @object_identifier, @compilation_context)
%
% compiles an "extends" relation between a prototype and a list of parents
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_extends_object_relation'([Ref| Refs], Obj, Ctx) :-
'$lgt_check_entity_reference'(object, Ref, Scope, Parent),
( '$lgt_term_template'(Obj, Parent) ->
throw(permission_error(extend, self, Obj))
; '$lgt_is_protocol'(Parent) ->
throw(type_error(object, Parent))
; '$lgt_is_category'(Parent) ->
throw(type_error(object, Parent))
; '$lgt_is_class'(Parent) ->
throw(domain_error(prototype, Parent))
; '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
throw(permission_error(extend, prototype, Parent))
; '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
throw(permission_error(extend, prototype, Parent))
; '$lgt_add_referenced_object'(Parent, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_extends_object_'(Obj, Parent, Scope))),
'$lgt_construct_prototype_functors'(Parent, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, _),
assertz('$lgt_pp_extended_object_'(Parent, Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Scope)),
'$lgt_compile_extends_object_relation'(Refs, Obj, Ctx)
).
'$lgt_compile_extends_object_relation'([], _, _).
% '$lgt_compile_extends_protocol_relation'(+list, @protocol_identifier, @compilation_context)
%
% compiles an "extends" relation between a protocol and a list of protocols
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_extends_protocol_relation'([Ref| Refs], Ptc, Ctx) :-
'$lgt_check_entity_reference'(protocol, Ref, Scope, ExtPtc),
( Ptc == ExtPtc ->
throw(permission_error(extend, self, Ptc))
; '$lgt_is_object'(ExtPtc) ->
throw(type_error(protocol, ExtPtc))
; '$lgt_is_category'(ExtPtc) ->
throw(type_error(protocol, ExtPtc))
; '$lgt_add_referenced_protocol'(ExtPtc, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_extends_protocol_'(Ptc, ExtPtc, Scope))),
'$lgt_construct_protocol_functors'(ExtPtc, Prefix, Dcl, _),
assertz('$lgt_pp_extended_protocol_'(ExtPtc, Ptc, Prefix, Dcl, Scope)),
'$lgt_compile_extends_protocol_relation'(Refs, Ptc, Ctx)
).
'$lgt_compile_extends_protocol_relation'([], _, _).
% '$lgt_compile_extends_category_relation'(+list, @category_identifier, @compilation_context)
%
% compiles an "extends" relation between a category and a list of categories
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_extends_category_relation'([Ref| Refs], Ctg, Ctx) :-
'$lgt_check_entity_reference'(category, Ref, Scope, ExtCtg),
( '$lgt_term_template'(Ctg, ExtCtg) ->
throw(permission_error(extend, self, Ctg))
; '$lgt_is_object'(ExtCtg) ->
throw(type_error(category, ExtCtg))
; '$lgt_is_protocol'(ExtCtg) ->
throw(type_error(category, ExtCtg))
; '$lgt_add_referenced_category'(ExtCtg, Ctx),
assertz('$lgt_pp_runtime_clause_'('$lgt_extends_category_'(Ctg, ExtCtg, Scope))),
'$lgt_construct_category_functors'(ExtCtg, Prefix, Dcl, Def, _),
assertz('$lgt_pp_extended_category_'(ExtCtg, Ctg, Prefix, Dcl, Def, Scope)),
'$lgt_compile_extends_category_relation'(Refs, Ctg, Ctx)
).
'$lgt_compile_extends_category_relation'([], _, _).
% '$lgt_compile_complements_object_relation'(+list, @category_identifier, @compilation_context)
%
% compiles a "complements" relation between a category and a list of objects
%
% note that the clause order ensures that instantiation errors will be caught by the call to
% the '$lgt_check_entity_reference'/4 predicate
'$lgt_compile_complements_object_relation'(Objs, Ctg, Ctx) :-
'$lgt_pp_category_'(Ctg, _, Dcl, Def, Rnm, _),
'$lgt_compile_complements_object_relation'(Objs, Ctg, Dcl, Def, Rnm, Ctx).
'$lgt_compile_complements_object_relation'([Obj| _], Ctg, _, _, _, _) :-
'$lgt_check'(object_identifier, Obj),
( '$lgt_term_template'(Obj, Ctg) ->
throw(permission_error(complement, self, Ctg))
; '$lgt_is_protocol'(Obj) ->
throw(type_error(object, Obj))
; '$lgt_is_category'(Obj) ->
throw(type_error(object, Obj))
; fail
).
'$lgt_compile_complements_object_relation'([Obj| _], Ctg, _, _, _, Ctx) :-
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(general, warning),
( '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags) ->
% loaded object
true
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, Flags))
% object being redefined in the same file as the complementing category;
% possible but unlikely in practice (except, maybe, in classroom examples)
),
Flags /\ 64 =\= 64,
Flags /\ 32 =\= 32,
% object compiled with complementing categories support disabled
'$lgt_source_file_context'(File, Lines),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(general), complementing_category_ignored(File, Lines, Ctg, Obj)),
fail.
'$lgt_compile_complements_object_relation'([Obj| Objs], Ctg, Dcl, Def, Rnm, Ctx) :-
'$lgt_add_referenced_object'(Obj, Ctx),
% ensure that a new complementing category will take preference over
% any previously loaded complementing category for the same object
'$lgt_comp_ctx_lines'(Ctx, Lines),
asserta('$lgt_pp_file_initialization_'(asserta('$lgt_complemented_object_'(Obj, Ctg, Dcl, Def, Rnm)), Lines)),
assertz('$lgt_pp_complemented_object_'(Obj, Ctg, Dcl, Def, Rnm)),
'$lgt_compile_complements_object_relation'(Objs, Ctg, Dcl, Def, Rnm, Ctx).
'$lgt_compile_complements_object_relation'([], _, _, _, _, _).
% '$lgt_is_prototype'(+entity_identifier)
%
% true if the argument is a defined prototype or a prototype being compiled
'$lgt_is_prototype'(Obj) :-
( '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _) ->
% existing object; first, check that is not being compiled as a different kind of entity
\+ '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Obj, _, _, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Obj, _, _, _, _, _)),
% second, check that it's a prototype
\+ '$lgt_instantiates_class_'(Obj, _, _),
\+ '$lgt_instantiates_class_'(_, Obj, _),
\+ '$lgt_specializes_class_'(Obj, _, _),
\+ '$lgt_specializes_class_'(_, Obj, _)
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _)) ->
% object defined earlier in the same file we're compiling; check that it's a prototype
\+ '$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(Obj, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(_, Obj, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(Obj, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(_, Obj, _))
; fail
).
% '$lgt_is_class'(+entity_identifier)
%
% true if the argument is a defined class or a class being compiled
'$lgt_is_class'(Obj) :-
( '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _) ->
% existing object; first, check that is not being compiled as a different kind of entity
\+ '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Obj, _, _, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Obj, _, _, _, _, _)),
% second, check that it's an instance or a class
( '$lgt_instantiates_class_'(Obj, _, _)
; '$lgt_instantiates_class_'(_, Obj, _)
; '$lgt_specializes_class_'(Obj, _, _)
; '$lgt_specializes_class_'(_, Obj, _)
), !
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _)) ->
% object defined earlier in the same file we're compiling; check that it's an instance or a class
( '$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(Obj, _, _))
; '$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(_, Obj, _))
; '$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(Obj, _, _))
; '$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(_, Obj, _))
), !
; fail
).
% '$lgt_is_object'(+entity_identifier)
%
% true if the argument is a defined object or an object being compiled
'$lgt_is_object'(Obj) :-
( '$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _) ->
% existing object; check that is not being compiled as a different kind of entity
\+ '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Obj, _, _, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Obj, _, _, _, _, _))
; '$lgt_pp_object_'(Obj, _, _, _, _, _, _, _, _, _, _) ->
% object being compiled
true
; '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Obj, _, _, _, _, _, _, _, _, _, _)) ->
% object defined earlier in the same file we're compiling
true
; fail
).
% '$lgt_is_protocol'(+entity_identifier)
%
% true if the argument is a defined protocol or a protocol being compiled
'$lgt_is_protocol'(Ptc) :-
( '$lgt_current_protocol_'(Ptc, _, _, _, _) ->
% existing protocol; check that is not being compiled as a different kind of entity
\+ '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Ptc, _, _, _, _, _, _, _, _, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Ptc, _, _, _, _, _))
; '$lgt_pp_protocol_'(Ptc, _, _, _, _) ->
% protocol being compiled
true
; '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Ptc, _, _, _, _)) ->
% protocol defined earlier in the same file we're compiling
true
; fail
).
% '$lgt_is_category'(+entity_identifier)
%
% true if the argument is a defined category or a category being compiled
'$lgt_is_category'(Ctg) :-
( '$lgt_current_category_'(Ctg, _, _, _, _, _) ->
% existing category; check that is not being compiled as a different kind of entity
\+ '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Ctg, _, _, _, _, _, _, _, _, _, _)),
\+ '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Ctg, _, _, _, _))
; '$lgt_pp_category_'(Ctg, _, _, _, _, _) ->
% category being compiled
true
; '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Ctg, _, _, _, _, _)) ->
% category defined earlier in the same file we're compiling
true
; fail
).
% '$lgt_inline_calls'(+atom)
%
% inline calls in linking clauses to Prolog module, built-in, and
% foreign predicates when compiling source files in optimal mode
%
% predicate definitions are only inlined when the clause body does
% not contain anonymous variables, which would break the predicate
% semantics (compared with the non-inlined definition) when calling
% the predicate from a bagof/3 or setof/3 goals
'$lgt_inline_calls'(protocol).
'$lgt_inline_calls'(category) :-
'$lgt_pp_category_'(_, _, _, Def, _, _),
'$lgt_inline_calls_def'(Def).
'$lgt_inline_calls'(object) :-
'$lgt_pp_object_'(_, _, _, Def, _, _, _, _, _, _, _),
'$lgt_inline_calls_def'(Def).
'$lgt_inline_calls_def'(Def) :-
'$lgt_compiler_flag'(optimize, on),
\+ '$lgt_pp_dynamic_',
% static entity
'$lgt_pp_number_of_clauses_rules_'(Functor, Arity, 1, _),
% predicate with a single clause
functor(Head, Functor, Arity),
\+ '$lgt_pp_dynamic_'(Head, _, _, _),
\+ '$lgt_pp_multifile_'(Head, _, _, _),
\+ '$lgt_pp_synchronized_'(Head, _, _, _),
% static, non-multifile, and no synchronization wrapper
'$lgt_pp_defines_predicate_'(Head, _, ExCtx, THead, _, user),
% source file user-defined predicate
'$lgt_pp_final_entity_term_'((THead :- TBody), _),
Head =.. [_| HeadArguments],
term_variables(HeadArguments, HeadVariables),
HeadArguments == HeadVariables,
% all head arguments are variables
\+ '$lgt_variable_aliasing'(Head),
% don't inline predicate definitions with variable aliasing in the clause
% head as this can result in optimization bugs when compiling predicate
% calls due to compile time variable bindings propagating to previous goals
% in the same clause body
'$lgt_inlining_candidate'(TBody, Functor/Arity),
% valid candidate for inlining
term_variables(THead, THeadVariables),
term_variables(TBody, TBodyVariables),
forall(
'$lgt_member'(TBodyVariable, TBodyVariables),
'$lgt_member_var'(TBodyVariable, THeadVariables)
),
% no anonymous variables in the body as this would change
% semantics for calls from bagof/3 and setof/3 goals
DefClauseOld =.. [Def, Head, _, _],
retractall('$lgt_pp_def_'(DefClauseOld)),
DefClauseNew =.. [Def, Head, ExCtx, TBody],
asserta('$lgt_pp_def_'(DefClauseNew)),
assertz('$lgt_pp_inline_predicate_'(Functor/Arity)),
% next candidate predicate
fail.
'$lgt_inline_calls_def'(_).
'$lgt_inlining_candidate'(':'(Module, Body), _) :-
% call to a Prolog module predicate
!,
atom(Module),
callable(Body).
'$lgt_inlining_candidate'(TBody, _) :-
'$lgt_control_construct'(TBody),
% don't inline control constructs
!,
fail.
'$lgt_inlining_candidate'(TBody, _) :-
'$lgt_logtalk_meta_predicate'(TBody, _, _),
% don't inline Logtalk built-in meta-predicates
!,
fail.
'$lgt_inlining_candidate'(TBody, _) :-
'$lgt_predicate_property'(TBody, built_in),
% Prolog built-in predicate
!.
'$lgt_inlining_candidate'(TBody, _) :-
% not all backend Prolog systems support a "foreign" predicate property
catch('$lgt_predicate_property'(TBody, foreign), _, fail),
% Prolog foreign predicate
!.
'$lgt_inlining_candidate'(TBody, Functor/Arity) :-
functor(TBody, TFunctor, TArity),
'$lgt_pp_referenced_object_message_'(Object, TFunctor/TArity, _, Functor/Arity, _, _),
Object == user,
% message to the "user" pseudo-object
!.
'$lgt_inlining_candidate'(TBody, _) :-
'$lgt_pp_defines_predicate_'(_, _, _, TBody, _, user),
% call to a local user-defined predicate
!.
% '$lgt_logtalk_control_construct'(@callable)
%
% table of Logtalk own control constructs
%
% when these control constructs are used as closures, the additional
% arguments must be appended to the arguments of the goal argument of
% the control construct, not as additional arguments of the control
% construct itself
'$lgt_logtalk_control_construct'(_ :: _).
'$lgt_logtalk_control_construct'(:: _).
'$lgt_logtalk_control_construct'(^^ _).
'$lgt_logtalk_control_construct'(_ << _).
'$lgt_logtalk_control_construct'({_}).
'$lgt_logtalk_control_construct'([_]).
% lambda expressions
'$lgt_logtalk_control_construct'(_ >> _).
'$lgt_logtalk_control_construct'(_ / _).
% '$lgt_control_construct'(?callable)
%
% partial table of control constructs; mainly used to help decide
% if a predicate definition should be compiled inline
'$lgt_control_construct'((_ , _)).
'$lgt_control_construct'((_ ; _)).
'$lgt_control_construct'((_ -> _)).
'$lgt_control_construct'(\+ _).
'$lgt_control_construct'(^^ _).
'$lgt_control_construct'(_ :: _).
'$lgt_control_construct'(:: _).
'$lgt_control_construct'(_ / _).
'$lgt_control_construct'(_ >> _).
'$lgt_control_construct'(_ << _).
'$lgt_control_construct'({_}).
'$lgt_control_construct'(':'(_, _)).
'$lgt_control_construct'(throw(_)).
'$lgt_control_construct'('*->'(_, _)) :-
'$lgt_prolog_built_in_predicate'('*->'(_, _)).
% '$lgt_cut_transparent_control_construct'(?callable)
%
% table of cut-transparent control constructs; used during
% compilation to check if call/1-N wrappers need to be keep
% for preserving source code semantics when the goal/closure
% argument is bound
'$lgt_cut_transparent_control_construct'(!).
'$lgt_cut_transparent_control_construct'((_ , _)).
'$lgt_cut_transparent_control_construct'((_ ; _)).
'$lgt_cut_transparent_control_construct'((_ -> _)).
'$lgt_cut_transparent_control_construct'('*->'(_, _)) :-
'$lgt_prolog_built_in_predicate'('*->'(_, _)).
% '$lgt_report_lint_issues'(+atom, @entity_identifier)
%
% reports detected lint issues found while compiling an entity
% (note that some lint issues are reported during compilation)
'$lgt_report_lint_issues'(Type, Entity) :-
'$lgt_report_missing_directives'(Type, Entity),
'$lgt_report_non_portable_calls'(Type, Entity),
'$lgt_report_missing_functions'(Type, Entity),
'$lgt_report_predicates_called_as_non_terminals'(Type, Entity),
'$lgt_report_non_tail_recursive_predicates'(Type, Entity),
'$lgt_report_unknown_entities'(Type, Entity),
'$lgt_report_unknown_messages'(Type, Entity),
'$lgt_report_naming_issues'(Type, Entity).
% '$lgt_source_file_context'(-atom, -pair(integer), -atom, -entity_identifier)
%
% returns file, lines, and entity source context for the last term read;
% it fails if the last attempt to read a term resulted in a syntax error
'$lgt_source_file_context'(File, Lines, Type, Entity) :-
'$lgt_pp_term_source_data_'(_, _, _, File, Lines),
'$lgt_pp_entity_'(Type, Entity, _).
% '$lgt_source_file_context'(-atom, -pair(integer))
%
% returns file and lines source context for the last term read;
% it fails if the last attempt to read a term resulted in a syntax error
'$lgt_source_file_context'(File, Lines) :-
'$lgt_pp_term_source_data_'(_, _, _, File, Lines).
% '$lgt_source_file_context'(@compilation_context, -atom, -pair(integer), -atom, -entity_identifier)
%
% returns file, lines, and entity source context for the last term read;
% it fails if the last attempt to read a term resulted in a syntax error;
% in the context of runtime compilation, returns dummy file and line values
'$lgt_source_file_context'(Ctx, File, Lines, Type, Entity) :-
'$lgt_source_file_context'(Ctx, File, Lines),
'$lgt_pp_entity_'(Type, Entity, _).
% '$lgt_source_file_context'(@compilation_context, -atom, -pair(integer))
%
% in the context of compiling a file, returns file and lines source context
% for the last term read and fails if the last attempt to read a term
% resulted in a syntax error; in the context of runtime compilation, returns
% dummy file and line values
'$lgt_source_file_context'(Ctx, File, Lines) :-
( '$lgt_comp_ctx_mode'(Ctx, runtime) ->
File = nil, Lines = '-'(-1, -1)
; '$lgt_pp_term_source_data_'(_, _, _, File, Lines) ->
true
; % e.g. when compiling auxiliary clauses at runtime
File = nil, Lines = 0-0
).
% '$lgt_report_unknown_entities'(+atom, @entity_identifier, +atom)
%
% reports any unknown referenced entities found while compiling an entity
'$lgt_report_unknown_entities'(_, _) :-
'$lgt_compiler_flag'(unknown_entities, silent),
!.
'$lgt_report_unknown_entities'(protocol, Entity) :-
% protocols can only reference other protocols
!,
'$lgt_report_unknown_protocols'(protocol, Entity).
'$lgt_report_unknown_entities'(Type, Entity) :-
'$lgt_report_unknown_objects'(Type, Entity),
'$lgt_report_unknown_protocols'(Type, Entity),
'$lgt_report_unknown_categories'(Type, Entity),
'$lgt_report_unknown_modules'(Type, Entity).
% '$lgt_report_unknown_objects'(+atom, @entity_identifier)
%
% reports any references to unknown objects found while compiling an entity
'$lgt_report_unknown_objects'(Type, Entity) :-
'$lgt_pp_referenced_object_'(Object, File, Lines),
% not a currently loaded object
\+ '$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _),
% not the object being compiled (self reference)
\+ '$lgt_pp_object_'(Object, _, _, _, _, _, _, _, _, _, _),
% not an object defined earlier in the source file being compiled
\+ '$lgt_pp_runtime_clause_'('$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, _)),
'$lgt_increment_compiling_warnings_counter',
( atom(Object),
'$lgt_prolog_feature'(modules, supported),
current_module(Object) ->
'$lgt_print_message'(warning(unknown_entities), module_used_as_object(File, Lines, Type, Entity, Object))
; '$lgt_print_message'(warning(unknown_entities), reference_to_unknown_object(File, Lines, Type, Entity, Object))
),
fail.
'$lgt_report_unknown_objects'(_, _).
% '$lgt_report_unknown_protocols'(+atom, @entity_identifier)
%
% reports any references to unknown protocols found while compiling an entity
'$lgt_report_unknown_protocols'(Type, Entity) :-
'$lgt_pp_referenced_protocol_'(Protocol, File, Lines),
% not a currently loaded protocol
\+ '$lgt_current_protocol_'(Protocol, _, _, _, _),
% not the protocol being compiled (self reference)
\+ '$lgt_pp_protocol_'(Protocol, _, _, _, _),
% not a protocol defined earlier in the source file being compiled
\+ '$lgt_pp_runtime_clause_'('$lgt_current_protocol_'(Protocol, _, _, _, _)),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(unknown_entities),
reference_to_unknown_protocol(File, Lines, Type, Entity, Protocol)
),
fail.
'$lgt_report_unknown_protocols'(_, _).
% '$lgt_report_unknown_categories'(+atom, @entity_identifier)
%
% reports any references to unknown categories found while compiling an entity
'$lgt_report_unknown_categories'(Type, Entity) :-
'$lgt_pp_referenced_category_'(Category, File, Lines),
% not a currently loaded category
\+ '$lgt_current_category_'(Category, _, _, _, _, _),
% not the category being compiled (self reference)
\+ '$lgt_pp_category_'(Category, _, _, _, _, _),
% not a category defined earlier in the source file being compiled
\+ '$lgt_pp_runtime_clause_'('$lgt_current_category_'(Category, _, _, _, _, _)),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(unknown_entities),
reference_to_unknown_category(File, Lines, Type, Entity, Category)
),
fail.
'$lgt_report_unknown_categories'(_, _).
% '$lgt_report_unknown_modules'(+atom, @entity_identifier)
%
% reports any references to unknown modules found while compiling an entity
'$lgt_report_unknown_modules'(Type, Entity) :-
'$lgt_prolog_feature'(modules, supported),
'$lgt_pp_referenced_module_'(Module, File, Lines),
% not a currently loaded module
\+ current_module(Module),
% not the module being compiled as an object (self reference)
\+ '$lgt_pp_module_'(Module),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(unknown_entities),
reference_to_unknown_module(File, Lines, Type, Entity, Module)
),
fail.
'$lgt_report_unknown_modules'(_, _).
% '$lgt_report_unknown_messages'(+atom, @entity_identifier)
%
% reports any unknown messages for loaded objects (including built-in objects) and
% calls to unknown predicates for loaded modules found while compiling an entity
'$lgt_report_unknown_messages'(_, _) :-
'$lgt_compiler_flag'(unknown_predicates, silent),
!.
'$lgt_report_unknown_messages'(Type, Entity) :-
'$lgt_pp_uses_predicate_'(Obj, Original, _, _, File, Lines),
nonvar(Obj),
functor(Original, Functor, Arity),
'$lgt_check_predicate_availability'(uses, Obj, Original, Original, Functor, Arity, Type, Entity, File, Lines),
fail.
'$lgt_report_unknown_messages'(Type, Entity) :-
'$lgt_pp_uses_non_terminal_'(Obj, Original, _, Pred, _, _, File, Lines),
nonvar(Obj),
functor(Pred, Functor, Arity),
'$lgt_check_predicate_availability'(uses, Obj, Original, Pred, Functor, Arity, Type, Entity, File, Lines),
fail.
'$lgt_report_unknown_messages'(Type, Entity) :-
'$lgt_prolog_feature'(modules, supported),
'$lgt_pp_use_module_predicate_'(Module, Original, _, _, File, Lines),
nonvar(Module),
functor(Original, Functor, Arity),
'$lgt_check_predicate_availability'(use_module, Module, Original, Original, Functor, Arity, Type, Entity, File, Lines),
fail.
'$lgt_report_unknown_messages'(Type, Entity) :-
'$lgt_prolog_feature'(modules, supported),
'$lgt_pp_use_module_non_terminal_'(Module, Original, _, Pred, _, _, File, Lines),
nonvar(Module),
functor(Pred, Functor, Arity),
'$lgt_check_predicate_availability'(use_module, Module, Original, Pred, Functor, Arity, Type, Entity, File, Lines),
fail.
'$lgt_report_unknown_messages'(_, _).
% auxiliary predicate for checking predicate availability for predicates
% listed in uses/2 and use_module/2 directives but only when the objects
% and modules are loaded
'$lgt_check_predicate_availability'(uses, Obj, Original, Pred, Functor, Arity, Type, Entity, File, Lines) :-
( \+ current_object(Obj) ->
true
; Obj::current_predicate(Functor/Arity) ->
true
; Obj == user,
( '$lgt_predicate_property'(Pred, built_in)
; catch('$lgt_predicate_property'(Pred, foreign), _, fail)
; catch('$lgt_predicate_property'(Pred, imported_from(_)), _, fail)
; '$lgt_pp_directive_'(dynamic(Functor/Arity))
; '$lgt_pp_directive_'(multifile(Functor/Arity))
) ->
true
; '$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(unknown_predicates),
message_not_understood(File, Lines, Type, Entity, Obj, Original)
)
).
'$lgt_check_predicate_availability'(use_module, Module, Original, Pred, Functor, Arity, Type, Entity, File, Lines) :-
( \+ current_module(Module) ->
true
; '$lgt_current_module_predicate'(Module, Functor/Arity) ->
true
; Module == user,
( '$lgt_predicate_property'(Pred, built_in)
; catch('$lgt_predicate_property'(Pred, foreign), _, fail)
; catch('$lgt_predicate_property'(Pred, imported_from(_)), _, fail)
; '$lgt_pp_directive_'(dynamic(Functor/Arity))
; '$lgt_pp_directive_'(multifile(Functor/Arity))
) ->
true
; '$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(unknown_predicates),
unknown_module_predicate(File, Lines, Type, Entity, Module, Original)
)
).
% '$lgt_report_naming_issues'(Type, Entity)
%
% reports names not following official coding guidelines
'$lgt_report_naming_issues'(Type, Entity) :-
( '$lgt_compiler_flag'(naming, warning) ->
'$lgt_report_entity_naming_issues'(Type, Entity),
'$lgt_report_predicate_naming_issues'(Type, Entity)
; true
).
'$lgt_report_entity_naming_issues'(Type, Entity) :-
functor(Entity, Name, _),
atom_chars(Name, Chars),
( '$lgt_camel_case_name'(Chars),
Warning = camel_case_entity_name(File, Lines, Type, Entity)
; '$lgt_name_with_digits_in_the_middle'(Chars),
Warning = entity_name_with_digits_in_the_middle(File, Lines, Type, Entity)
),
( '$lgt_pp_referenced_object_'(Entity, File, Lines) ->
true
; '$lgt_pp_referenced_protocol_'(Entity, File, Lines) ->
true
; '$lgt_pp_referenced_category_'(Entity, File, Lines) ->
true
; '$lgt_pp_file_paths_flags_'(_, _, File, _, _),
Lines = '-'(-1, -1)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_entity_naming_issues'(_, _).
'$lgt_report_predicate_naming_issues'(Type, Entity) :-
( '$lgt_pp_public_'(Name, Arity, _, _)
; '$lgt_pp_protected_'(Name, Arity, _, _)
; '$lgt_pp_private_'(Name, Arity, _, _)
),
% backtrack over all declared predicates
\+ '$lgt_pp_non_terminal_'(Name, _, Arity),
% not declared as non-terminals
functor(Template, Name, Arity),
\+ '$lgt_pp_defines_predicate_'(Template, _, _, _, _, _),
% not defined
atom_chars(Name, Chars),
( '$lgt_camel_case_name'(Chars),
Warning = camel_case_predicate_name(File, Lines, Type, Entity, Name/Arity)
; '$lgt_name_with_digits_in_the_middle'(Chars),
Warning = predicate_name_with_digits_in_the_middle(File, Lines, Type, Entity, Name/Arity)
),
( '$lgt_pp_predicate_declaration_location_'(Name, Arity, File, Lines) ->
true
; '$lgt_source_file_context'(File, _),
Lines = '-'(-1, -1)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_predicate_naming_issues'(Type, Entity) :-
'$lgt_pp_non_terminal_'(Name, Arity, ExtArity),
% declared non-terminal (in a scope directive)
functor(Template, Name, ExtArity),
\+ '$lgt_pp_defines_predicate_'(Template, _, _, _, _, _),
% not defined
atom_chars(Name, Chars),
( '$lgt_camel_case_name'(Chars),
Warning = camel_case_non_terminal_name(File, Lines, Type, Entity, Name//Arity)
; '$lgt_name_with_digits_in_the_middle'(Chars),
Warning = non_terminal_name_with_digits_in_the_middle(File, Lines, Type, Entity, Name//Arity)
),
( '$lgt_pp_predicate_declaration_location_'(Name, ExtArity, File, Lines) ->
true
; '$lgt_source_file_context'(File, _),
Lines = '-'(-1, -1)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_predicate_naming_issues'(Type, Entity) :-
'$lgt_pp_defines_predicate_'(_, Name/Arity, _, _, _, user),
\+ '$lgt_pp_defines_non_terminal_'(Name, _, Arity),
\+ '$lgt_pp_public_'(Name, Arity, _, _),
\+ '$lgt_pp_protected_'(Name, Arity, _, _),
\+ '$lgt_pp_private_'(Name, Arity, _, _),
\+ '$lgt_pp_non_terminal_'(Name, _, Arity),
% user-defined local predicate
atom_chars(Name, Chars),
( '$lgt_camel_case_name'(Chars),
Warning = camel_case_predicate_name(File, Lines, Type, Entity, Name/Arity)
; '$lgt_name_with_digits_in_the_middle'(Chars),
Warning = predicate_name_with_digits_in_the_middle(File, Lines, Type, Entity, Name/Arity)
),
( '$lgt_pp_predicate_definition_location_'(Name, Arity, File, Lines) ->
true
; '$lgt_source_file_context'(File, _),
Lines = '-'(-1, -1)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_predicate_naming_issues'(Type, Entity) :-
'$lgt_pp_defines_non_terminal_'(Name, Arity, ExtArity),
'$lgt_pp_defines_predicate_'(_, Name/ExtArity, _, _, _, user),
\+ '$lgt_pp_public_'(Name, ExtArity, _, _),
\+ '$lgt_pp_protected_'(Name, ExtArity, _, _),
\+ '$lgt_pp_private_'(Name, ExtArity, _, _),
\+ '$lgt_pp_non_terminal_'(Name, Arity, ExtArity),
% user-defined local non-terminal
atom_chars(Name, Chars),
( '$lgt_camel_case_name'(Chars),
Warning = camel_case_non_terminal_name(File, Lines, Type, Entity, Name//Arity)
; '$lgt_name_with_digits_in_the_middle'(Chars),
Warning = non_terminal_name_with_digits_in_the_middle(File, Lines, Type, Entity, Name//Arity)
),
( '$lgt_pp_predicate_definition_location_'(Name, ExtArity, File, Lines) ->
true
; '$lgt_source_file_context'(File, _),
Lines = '-'(-1, -1)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_predicate_naming_issues'(_, _).
'$lgt_camel_case_name'(Chars) :-
'$lgt_append'([_| _], [Char1, Char2| _], Chars),
a @=< Char1, Char1 @=< z,
'A' @=< Char2, Char2 @=< 'Z',
!.
'$lgt_name_with_digits_in_the_middle'(Chars) :-
'$lgt_append'([_| _], [Char1, Char2| _], Chars),
'0' @=< Char1, Char1 @=< '9',
('0' @> Char2; Char2 @> '9'),
!.
% '$lgt_add_def_clause'(+callable, +atom, +integer, -callable, +compilation_context)
%
% adds a "def" clause (used to translate between user predicate names and internal names)
% and returns the compiled clause head
'$lgt_add_def_clause'(Head, Functor, Arity, THead, Ctx) :-
functor(HeadTemplate, Functor, Arity),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, Lines, _),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(THeadTemplate, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(HeadTemplate, THeadTemplate, ExCtxTemplate),
( '$lgt_pp_object_'(_, _, _, Def, _, _, _, _, _, _, _) ->
true
; '$lgt_pp_category_'(_, _, _, Def, _, _)
),
'$lgt_construct_def_clause'(Def, HeadTemplate, ExCtxTemplate, THeadTemplate, Clause),
assertz('$lgt_pp_def_'(Clause)),
% the following two calls have side effects, thus ...
'$lgt_check_for_redefined_built_in'(Mode, HeadTemplate, ExCtxTemplate, THeadTemplate, Lines),
'$lgt_remember_defined_predicate'(Mode, HeadTemplate, Functor/Arity, ExCtxTemplate, THeadTemplate),
% ... we need to delay output unifications to after they succeed
Head = HeadTemplate,
ExCtx = ExCtxTemplate,
THead = THeadTemplate.
% '$lgt_add_ddef_clause'(+callable, +atom, +integer, -callable, +compilation_context)
%
% adds a "ddef" clause (used to translate between user predicate names and internal names)
% and returns the compiled clause head
'$lgt_add_ddef_clause'(Head, Functor, Arity, THead, Ctx) :-
functor(HeadTemplate, Functor, Arity),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, Prefix, _, _, ExCtx, Mode, _, Lines, _),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(THeadTemplate, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(HeadTemplate, THeadTemplate, ExCtxTemplate),
% only objects can define clauses for dynamic predicates
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, DDef, _, _),
'$lgt_construct_def_clause'(DDef, HeadTemplate, ExCtxTemplate, THeadTemplate, Clause),
assertz('$lgt_pp_ddef_'(Clause)),
% the following two calls have side effects, thus ...
'$lgt_check_for_redefined_built_in'(Mode, HeadTemplate, ExCtxTemplate, THeadTemplate, Lines),
'$lgt_remember_defined_predicate'(Mode, HeadTemplate, Functor/Arity, ExCtxTemplate, THeadTemplate),
% ... we need to delay output unifications to after they succeed
Head = HeadTemplate,
ExCtx = ExCtxTemplate,
THead = THeadTemplate.
% '$lgt_construct_def_clause'(+callable, +callable, +execution_context, +callable, -clause)
%
% constructs a "def" or "ddef" clause (used to translate between user predicate names and internal names)
'$lgt_construct_def_clause'(Def, Head, ExCtx, THead, Clause) :-
( '$lgt_pp_synchronized_'(Head, Mutex, _, _) ->
'$lgt_wrap_compiled_head'(Head, THead, ExCtx, Call),
( '$lgt_prolog_feature'(threads, supported) ->
Clause =.. [Def, Head, ExCtx, with_mutex(Mutex,Call)]
; % in single-threaded systems, with_mutex/2 is equivalent to once/1
Clause =.. [Def, Head, ExCtx, once(Call)]
)
; '$lgt_pp_coinductive_head_'(Head, ExCtx, TCHead) ->
'$lgt_wrap_compiled_head'(Head, TCHead, ExCtx, Call),
Clause =.. [Def, Head, ExCtx, Call]
; '$lgt_wrap_compiled_head'(Head, THead, ExCtx, Call),
Clause =.. [Def, Head, ExCtx, Call]
).
% predicates for wrapping/unwrapping compiled predicate heads to deal with
% compilation in debug mode
%
% the wrapping when in compilation mode ensures that indirect predicate calls
% (e.g. when sending a message) can also be intercepted by debug handlers
'$lgt_wrap_compiled_head'(Head, THead, ExCtx, Call) :-
( '$lgt_compiler_flag'(debug, on) ->
Call = '$lgt_debug'(goal(Head,THead), ExCtx)
; Call = THead
).
'$lgt_unwrap_compiled_head'('$lgt_debug'(goal(_,THead), _), THead) :-
!.
'$lgt_unwrap_compiled_head'(THead, THead).
% '$lgt_add_def_fail_clause'(@callable, @compilation_context)
%
% adds a "def clause" (used to translate a predicate call) where the
% definition is simply fail due to the predicate being declared, static,
% but undefined (as per closed-world assumption)
'$lgt_add_def_fail_clause'(Head, Ctx) :-
( '$lgt_pp_object_'(_, _, _, Def, _, _, _, _, _, _, _) ->
true
; '$lgt_pp_category_'(_, _, _, Def, _, _)
),
Clause =.. [Def, Head, _, fail],
assertz('$lgt_pp_def_'(Clause)),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _),
'$lgt_check_for_redefined_built_in'(Mode, Head, _, fail, Lines).
% '$lgt_check_for_redefined_built_in'(@compilation_mode, @callable, @execution_context, @callable, @pair)
%
% this predicate is called when adding a def/ddef clause after finding the first clause
% for a predicate or when no clauses are defined for a declared predicate
'$lgt_check_for_redefined_built_in'(runtime, _, _, _, _).
'$lgt_check_for_redefined_built_in'(compile(_,_,_), Head, ExCtx, THead, Lines) :-
'$lgt_logtalk_built_in_predicate'(Head, _),
!,
assertz('$lgt_pp_redefined_built_in_'(Head, ExCtx, THead)),
retractall('$lgt_pp_non_portable_predicate_'(Head, _, _)),
( '$lgt_compiler_flag'(redefined_built_ins, warning) ->
functor(Head, Functor, Arity),
'$lgt_source_file_context'(File, _, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(redefined_built_ins),
redefined_logtalk_built_in_predicate(File, Lines, Type, Entity, Functor/Arity)
)
; true
).
'$lgt_check_for_redefined_built_in'(compile(_,_,_), Head, ExCtx, THead, Lines) :-
'$lgt_prolog_built_in_predicate'(Head),
!,
assertz('$lgt_pp_redefined_built_in_'(Head, ExCtx, THead)),
retractall('$lgt_pp_non_portable_predicate_'(Head, _, _)),
( '$lgt_compiler_flag'(redefined_built_ins, warning) ->
functor(Head, Functor, Arity),
'$lgt_source_file_context'(File, _, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(redefined_built_ins),
redefined_prolog_built_in_predicate(File, Lines, Type, Entity, Functor/Arity)
)
; true
).
'$lgt_check_for_redefined_built_in'(compile(_,_,_), _, _, _, _).
% '$lgt_remember_defined_predicate'(@compilation_mode, @callable, +predicate_indicator, +execution_context, @callable)
%
% it's necessary to remember which predicates are defined in order to deal with
% redefinition of built-in predicates, detect missing predicate directives, and
% speed up compilation of other clauses for the same predicates
'$lgt_remember_defined_predicate'(Mode, Head, PI, ExCtx, THead) :-
( Mode = compile(aux,_,_) ->
assertz('$lgt_pp_defines_predicate_'(Head, PI, ExCtx, THead, Mode, aux)),
retractall('$lgt_pp_previous_predicate_'(_, aux)),
assertz('$lgt_pp_previous_predicate_'(Head, aux))
; % compile(user,_,_) or runtime
assertz('$lgt_pp_defines_predicate_'(Head, PI, ExCtx, THead, Mode, user)),
retractall('$lgt_pp_previous_predicate_'(_, user)),
assertz('$lgt_pp_previous_predicate_'(Head, user))
).
% '$lgt_report_variable_naming_issues'(+list, +atom, +compound)
%
% reports variable naming issues as per official coding guidelines
'$lgt_report_variable_naming_issues'([], _, _) :-
!.
'$lgt_report_variable_naming_issues'(_, _, _) :-
'$lgt_compiler_flag'(naming, silent),
!.
'$lgt_report_variable_naming_issues'(Names, File, Lines) :-
'$lgt_member'(Name=_, Names),
'$lgt_non_camel_case_name'(Name),
( '$lgt_pp_entity_'(Type, Entity, _) ->
Warning = non_camel_case_variable_name(File, Lines, Type, Entity, Name)
; Warning = non_camel_case_variable_name(File, Lines, Name)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_variable_naming_issues'(Names, File, Lines) :-
'$lgt_member'(Name=_, Names),
atom_chars(Name, Chars),
'$lgt_name_with_digits_in_the_middle'(Chars),
( '$lgt_pp_entity_'(Type, Entity, _) ->
Warning = variable_name_with_digits_in_the_middle(File, Lines, Type, Entity, Name)
; Warning = variable_name_with_digits_in_the_middle(File, Lines, Name)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_variable_naming_issues'(Names, File, Lines) :-
'$lgt_name_pair'(Names, Name, OtherName),
'$lgt_similar_names'(Name, OtherName),
( '$lgt_pp_entity_'(Type, Entity, _) ->
Warning = variable_names_differ_only_on_case(File, Lines, Type, Entity, Name, OtherName)
; Warning = variable_names_differ_only_on_case(File, Lines, Name, OtherName)
),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(warning(naming), Warning),
fail.
'$lgt_report_variable_naming_issues'(_, _, _).
'$lgt_non_camel_case_name'(Name) :-
atom_chars(Name, Chars),
'$lgt_append'(_, [Char1, '_', Char2| _], Chars),
Char1 \== '_',
Char2 \== '_',
!.
'$lgt_name_pair'([Name=_| Names], Name, OtherName) :-
'$lgt_member'(OtherName=_, Names).
'$lgt_name_pair'([_| Names], Name, OtherName) :-
'$lgt_name_pair'(Names, Name, OtherName).
'$lgt_similar_names'(Name, OtherName) :-
atom_length(Name, Length),
atom_length(OtherName, Length),
% same length
sub_atom(Name, _, 1, 0, Last),
\+ ('0' @=< Last, Last @=< '9'),
sub_atom(OtherName, _, 1, 0, OtherLast),
\+ ('0' @=< OtherLast, OtherLast @=< '9'),
% not ending with a digit
'$lgt_to_lower_case'(Name, NameLowerCase),
'$lgt_to_lower_case'(OtherName, OtherNameLowerCase),
NameLowerCase == OtherNameLowerCase.
'$lgt_to_lower_case'(Name, NameLowerCase) :-
atom_codes(Name, Codes),
'$lgt_to_lower_case_codes'(Codes, CodesLowerCase),
atom_codes(NameLowerCase, CodesLowerCase).
'$lgt_to_lower_case_codes'([], []).
'$lgt_to_lower_case_codes'([Code| Codes], [LowerCode| LowerCodes]) :-
65 =< Code, Code @=< 90,
!,
LowerCode is 97 + Code - 65,
'$lgt_to_lower_case_codes'(Codes, LowerCodes).
'$lgt_to_lower_case_codes'([Code| Codes], [Code| LowerCodes]) :-
'$lgt_to_lower_case_codes'(Codes, LowerCodes).
% '$lgt_update_ddef_table'(+atom, @callable, @callable)
%
% retracts a dynamic "ddef clause" (used to translate a predicate call)
% and updated the predicate lookup caches if there are no more (local)
% clauses for the predicate otherwise does nothing; this is required in
% order to allow definitions in ancestor entities to be found
'$lgt_update_ddef_table'(DDef, Head, THead) :-
'$lgt_term_template'(THead, GTHead),
( clause(GTHead, _) ->
true
; DDefClause =.. [DDef, Head, _, _],
retractall(DDefClause),
'$lgt_clean_lookup_caches'(Head)
).
% '$lgt_update_ddef_table_opt'(+callable)
%
% retracts a dynamic "ddef clause" (used to translate a predicate call)
% and updates the predicate lookup caches if there are no more (local)
% clauses for the predicate otherwise does nothing; this is required in
% order to allow definitions in ancestor entities to be found when all
% the overriding clauses in an intermediate object are retracted
'$lgt_update_ddef_table_opt'(true).
'$lgt_update_ddef_table_opt'(update(Head, THead, Clause)) :-
( clause(THead, _) ->
true
; retractall(Clause),
'$lgt_clean_lookup_caches'(Head)
).
% '$lgt_generate_entity_code'(+atom, +compilation_context)
%
% generates code for the entity being compiled
'$lgt_generate_entity_code'(protocol, _) :-
'$lgt_generate_protocol_clauses',
'$lgt_generate_protocol_directives'.
'$lgt_generate_entity_code'(object, Ctx) :-
'$lgt_generate_def_table_clauses'(Ctx),
'$lgt_compile_predicate_calls'(compile_time),
'$lgt_generate_object_clauses',
'$lgt_generate_object_directives',
'$lgt_generate_file_object_initialization_goal'.
'$lgt_generate_entity_code'(category, Ctx) :-
'$lgt_generate_def_table_clauses'(Ctx),
'$lgt_compile_predicate_calls'(compile_time),
'$lgt_generate_category_clauses',
'$lgt_generate_category_directives',
'$lgt_generate_file_category_initialization_goal'.
'$lgt_generate_object_directives' :-
'$lgt_generate_object_dynamic_directives',
'$lgt_generate_object_discontiguous_directives'.
'$lgt_generate_category_directives' :-
'$lgt_generate_category_dynamic_directives',
'$lgt_generate_category_discontiguous_directives'.
'$lgt_generate_protocol_directives' :-
( '$lgt_pp_dynamic_' ->
% add the necessary directives to allow abolishing the protocol
'$lgt_pp_protocol_'(_, _, Dcl, Rnm, _),
assertz('$lgt_pp_directive_'(dynamic(Dcl/4))),
assertz('$lgt_pp_directive_'(dynamic(Dcl/5))),
assertz('$lgt_pp_directive_'(dynamic(Rnm/3)))
; true
).
'$lgt_generate_object_dynamic_directives' :-
( '$lgt_pp_dynamic_' ->
% add the necessary directives to allow abolishing the object
'$lgt_generate_dynamic_object_dynamic_directives'
; '$lgt_generate_static_object_dynamic_directives'
).
'$lgt_generate_dynamic_object_dynamic_directives' :-
'$lgt_pp_object_'(_, _, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, _),
assertz('$lgt_pp_directive_'(dynamic(Dcl/4))),
assertz('$lgt_pp_directive_'(dynamic(Dcl/6))),
assertz('$lgt_pp_directive_'(dynamic(Def/3))),
assertz('$lgt_pp_directive_'(dynamic(Def/5))),
assertz('$lgt_pp_directive_'(dynamic(Super/5))),
assertz('$lgt_pp_directive_'(dynamic(IDcl/6))),
assertz('$lgt_pp_directive_'(dynamic(IDef/5))),
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
assertz('$lgt_pp_directive_'(dynamic(DDcl/2)))
; true
),
assertz('$lgt_pp_directive_'(dynamic(DDef/3))),
assertz('$lgt_pp_directive_'(dynamic(Rnm/3))),
'$lgt_generate_dynamic_entity_dynamic_predicate_directives'.
'$lgt_generate_dynamic_entity_dynamic_predicate_directives' :-
'$lgt_pp_def_'(Clause),
% only local table; reject linking clauses
Clause \= (_ :- _),
arg(3, Clause, Call),
'$lgt_unwrap_compiled_head'(Call, Pred),
functor(Pred, Functor, Arity),
assertz('$lgt_pp_directive_'(dynamic(Functor/Arity))),
fail.
'$lgt_generate_dynamic_entity_dynamic_predicate_directives' :-
'$lgt_pp_ddef_'(Clause),
% only local table; reject linking clauses
Clause \= (_ :- _),
arg(3, Clause, Call),
'$lgt_unwrap_compiled_head'(Call, Pred),
functor(Pred, Functor, Arity),
assertz('$lgt_pp_directive_'(dynamic(Functor/Arity))),
fail.
'$lgt_generate_dynamic_entity_dynamic_predicate_directives'.
'$lgt_generate_static_object_dynamic_directives' :-
'$lgt_pp_object_'(_, Prefix, _, _, _, _, _, DDcl, DDef, _, _),
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
assertz('$lgt_pp_directive_'(dynamic(DDcl/2)))
; true
),
assertz('$lgt_pp_directive_'(dynamic(DDef/3))),
'$lgt_pp_dynamic_'(Head, _, _, _),
functor(Head, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
assertz('$lgt_pp_directive_'(dynamic(TFunctor/TArity))),
fail.
'$lgt_generate_static_object_dynamic_directives'.
'$lgt_generate_object_discontiguous_directives' :-
'$lgt_pp_object_'(_, Prefix, _, _, _, _, _, _, _, _, _),
'$lgt_pp_discontiguous_'(Head, _, _),
functor(Head, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
assertz('$lgt_pp_directive_'(discontiguous(TFunctor/TArity))),
fail.
'$lgt_generate_object_discontiguous_directives'.
'$lgt_generate_category_dynamic_directives' :-
( '$lgt_pp_dynamic_' ->
% add the necessary directives to allow abolishing the category
'$lgt_pp_category_'(_, _, Dcl, Def, Rnm, _),
assertz('$lgt_pp_directive_'(dynamic(Dcl/4))),
assertz('$lgt_pp_directive_'(dynamic(Dcl/5))),
assertz('$lgt_pp_directive_'(dynamic(Def/3))),
assertz('$lgt_pp_directive_'(dynamic(Rnm/3))),
'$lgt_generate_dynamic_entity_dynamic_predicate_directives'
; true
).
'$lgt_generate_category_discontiguous_directives' :-
'$lgt_pp_category_'(_, Prefix, _, _, _, _),
'$lgt_pp_discontiguous_'(Head, _, _),
functor(Head, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
assertz('$lgt_pp_directive_'(discontiguous(TFunctor/TArity))),
fail.
'$lgt_generate_category_discontiguous_directives'.
'$lgt_generate_object_clauses' :-
( '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
% object plays the role of a class
'$lgt_generate_ic_clauses'
; '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
% object plays the role of a class
'$lgt_generate_ic_clauses'
; % objects without an instantiation or specialization relation
% play the role of prototypes
'$lgt_generate_prototype_clauses'
).
% '$lgt_generate_dcl_table_clauses'(+atom, -atom)
%
% a predicate declaration table clause is only generated if there is a
% scope declaration for the predicate; the second argument returns the
% atom "true" if there are local clauses and the atom "false" otherwise
%
% the table clauses use a bit pattern representation for the predicate
% properties for compactness and access performance
'$lgt_generate_dcl_table_clauses'(Dcl, _) :-
( '$lgt_pp_public_'(Functor, Arity, _, _), Scope = p(p(p))
; '$lgt_pp_protected_'(Functor, Arity, _, _), Scope = p(p)
; '$lgt_pp_private_'(Functor, Arity, _, _), Scope = p
),
functor(Pred, Functor, Arity),
( '$lgt_pp_meta_predicate_'(Pred, Template, _, _) ->
Meta = Template,
MetaPredicate = 64 % 0b01000000
; Meta = no,
MetaPredicate = 0
),
( '$lgt_pp_coinductive_head_'(Pred, _, _) ->
Coinductive = 32 % 0b00100000
; Coinductive = 0
),
( '$lgt_pp_multifile_'(Pred, _, _, _) ->
Multifile = 16 % 0b00010000
; Multifile = 0
),
( '$lgt_pp_non_terminal_'(Functor, _, Arity) ->
NonTerminal = 8 % 0b00001000
; NonTerminal = 0
),
( '$lgt_pp_synchronized_'(Pred, _, _, _) ->
Synchronized = 4 % 0b00000100
; Synchronized = 0
),
( '$lgt_pp_dynamic_' ->
Dynamic = 2 % 0b00000010
; '$lgt_pp_dynamic_'(Pred, _, _, _) ->
Dynamic = 2 % 0b00000010
; Dynamic = 0
),
Flags is MetaPredicate + Coinductive + Multifile + NonTerminal + Synchronized + Dynamic,
Fact =.. [Dcl, Pred, Scope, Meta, Flags],
assertz('$lgt_pp_dcl_'(Fact)),
fail.
'$lgt_generate_dcl_table_clauses'(_, Local) :-
( '$lgt_pp_dcl_'(_) ->
Local = true
; Local = false
).
% '$lgt_generate_def_table_clauses'(+compilation_context)
%
% generates predicate definition table clauses for undefined but
% declared (using a predicate directive) predicates
'$lgt_generate_def_table_clauses'(Ctx) :-
\+ '$lgt_pp_dynamic_',
% static entities only otherwise abolishing the dynamic entity would result
% in an attempt to retract a clause for the fail/0 built-in control construct
( '$lgt_pp_complemented_object_'(_, _, _, _, _) ->
'$lgt_compiler_flag'(complements, restrict)
; true
),
% complementing categories can add a scope directive for predicates that
% are defined in the complemented objects; for objects compiled with the
% complements flag set to allow, we must allow lookup of the predicate
% definition in the object itself (and elsewhere in its ancestors)
( '$lgt_pp_public_'(Functor, Arity, _, _)
; '$lgt_pp_protected_'(Functor, Arity, _, _)
; '$lgt_pp_private_'(Functor, Arity, _, _)
; '$lgt_pp_synchronized_'(Head, _, _, _)
; '$lgt_pp_coinductive_head_'(Head, _, _)
; '$lgt_pp_discontiguous_'(Head, _, _)
),
functor(Head, Functor, Arity),
\+ '$lgt_pp_multifile_'(Head, _, _, _),
\+ '$lgt_pp_dynamic_'(Head, _, _, _),
\+ '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _),
% declared, static, but undefined predicate;
% local calls must fail (as per closed-world assumption)
'$lgt_add_def_fail_clause'(Head, Ctx),
fail.
'$lgt_generate_def_table_clauses'(Ctx) :-
'$lgt_pp_entity_'(Type, _, Prefix),
( Type == object,
% categories cannot contain clauses for dynamic predicates
'$lgt_pp_dynamic_'(Head, _, _, _)
; '$lgt_pp_multifile_'(Head, _, _, _),
\+ '$lgt_pp_dynamic_'(Head, _, _, _)
),
\+ '$lgt_pp_defines_predicate_'(Head, _, _, _, _, _),
% dynamic and/or multifile predicate with no initial set of clauses
'$lgt_comp_ctx_prefix'(Ctx, Prefix),
functor(Head, Functor, Arity),
( \+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _),
\+ '$lgt_pp_synchronized_'(Head, _, _, _),
\+ '$lgt_pp_coinductive_head_'(Head, _, _),
\+ '$lgt_pp_multifile_'(Head, _, _, _) ->
'$lgt_add_ddef_clause'(Head, Functor, Arity, _, Ctx)
; '$lgt_add_def_clause'(Head, Functor, Arity, _, Ctx)
),
fail.
'$lgt_generate_def_table_clauses'(_).
'$lgt_generate_protocol_clauses' :-
'$lgt_pp_protocol_'(Ptc, _, Dcl, Rnm, _),
% first, generate the local table of predicate declarations
'$lgt_generate_dcl_table_clauses'(Dcl, Local),
% second, generate linking clauses for accessing both local
% declarations and declarations in related entities (some
% linking clauses depend on the existence of local predicate
% declarations)
'$lgt_generate_protocol_local_clauses'(Local, Ptc, Dcl),
'$lgt_generate_protocol_extends_clauses'(Dcl, Rnm),
% third, add a catchall clause if necessary
'$lgt_generate_protocol_catchall_clauses'(Dcl).
'$lgt_generate_protocol_local_clauses'(true, Ptc, PDcl) :-
Head =.. [PDcl, Pred, Scope, Meta, Flags, Ptc],
Body =.. [PDcl, Pred, Scope, Meta, Flags],
assertz('$lgt_pp_dcl_'((Head:-Body))).
'$lgt_generate_protocol_local_clauses'(false, _, _).
'$lgt_generate_protocol_extends_clauses'(Dcl, Rnm) :-
'$lgt_pp_extended_protocol_'(ExtPtc, _, _, ExtDcl, RelationScope),
( RelationScope == (public) ->
Lookup =.. [ExtDcl, Pred, Scope, Meta, Flags, Ctn]
; RelationScope == protected ->
Lookup0 =.. [ExtDcl, Pred, Scope2, Meta, Flags, Ctn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [ExtDcl, Pred, _, Meta, Flags, Ctn]
),
( '$lgt_pp_predicate_alias_'(ExtPtc, _, _, _, _, _) ->
Head =.. [Dcl, Alias, Scope, Meta, Flags, Ctn],
Rename =.. [Rnm, ExtPtc, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [Dcl, Pred, Scope, Meta, Flags, Ctn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_protocol_extends_clauses'(_, _).
% when a static protocol is empty, i.e. when it does not contain any predicate
% declarations, and does not extend other protocols, we need a catchall clause
% in order to prevent predicate existence errors when sending a message to an
% object implementing (directly or indirectly) the protocol
'$lgt_generate_protocol_catchall_clauses'(Dcl) :-
( '$lgt_pp_dcl_'(_) ->
% local or inherited predicate declarations exist
true
; % empty, standalone protocol
'$lgt_pp_dynamic_' ->
% dynamic protocol; calls to the dynamic predicate implementing the
% predicate declaration table fail when there are no clauses
true
; % static protocol; generate a catchall clause as the predicate
% implementing the predicate declaration table is also static
functor(Head, Dcl, 5),
assertz('$lgt_pp_dcl_'((Head:-fail)))
).
'$lgt_generate_category_clauses' :-
'$lgt_pp_category_'(Ctg, _, Dcl, Def, Rnm, _),
'$lgt_generate_category_dcl_clauses'(Ctg, Dcl, Rnm),
'$lgt_generate_category_def_clauses'(Ctg, Def, Rnm).
'$lgt_generate_category_dcl_clauses'(Ctg, Dcl, Rnm) :-
% first, generate the local table of predicate declarations
'$lgt_generate_dcl_table_clauses'(Dcl, Local),
% second, generate linking clauses for accessing both local
% declarations and declarations in related entities (some
% linking clauses depend on the existence of local predicate
% declarations)
'$lgt_generate_category_local_dcl_clauses'(Local, Ctg, Dcl),
'$lgt_generate_category_implements_dcl_clauses'(Dcl, Rnm),
'$lgt_generate_category_extends_dcl_clauses'(Dcl, Rnm),
% third, add a catchall clause if necessary
'$lgt_generate_category_catchall_dcl_clauses'(Dcl).
'$lgt_generate_category_local_dcl_clauses'(true, Ctg, CDcl) :-
Head =.. [CDcl, Pred, Scope, Meta, Flags, Ctg],
Body =.. [CDcl, Pred, Scope, Meta, Flags],
assertz('$lgt_pp_dcl_'((Head:-Body))).
'$lgt_generate_category_local_dcl_clauses'(false, _, _).
'$lgt_generate_category_implements_dcl_clauses'(CDcl, Rnm) :-
'$lgt_pp_implemented_protocol_'(Ptc, _, _, PDcl, RelationScope),
( RelationScope == (public) ->
Lookup =.. [PDcl, Pred, Scope, Meta, Flags, Ctn]
; RelationScope == protected ->
Lookup0 =.. [PDcl, Pred, Scope2, Meta, Flags, Ctn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [PDcl, Pred, _, Meta, Flags, Ctn]
),
( '$lgt_pp_predicate_alias_'(Ptc, _, _, _, _, _) ->
Head =.. [CDcl, Alias, Scope, Meta, Flags, Ctn],
Rename =.. [Rnm, Ptc, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [CDcl, Pred, Scope, Meta, Flags, Ctn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_category_implements_dcl_clauses'(_, _).
'$lgt_generate_category_extends_dcl_clauses'(CDcl, Rnm) :-
'$lgt_pp_extended_category_'(Ctg, _, _, ECDcl, _, RelationScope),
( RelationScope == (public) ->
Lookup =.. [ECDcl, Pred, Scope, Meta, Flags, Ctn]
; RelationScope == protected ->
Lookup0 =.. [ECDcl, Pred, Scope2, Meta, Flags, Ctn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [ECDcl, Pred, _, Meta, Flags, Ctn]
),
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [CDcl, Alias, Scope, Meta, Flags, Ctn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [CDcl, Pred, Scope, Meta, Flags, Ctn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_category_extends_dcl_clauses'(_, _).
% when a static category contains no predicate declarations, does not implement any
% protocol, and does not extend other categories, we need a catchall clause in order
% to prevent predicate existence errors when sending a message to an object importing
% (directly or indirectly) the category
'$lgt_generate_category_catchall_dcl_clauses'(Dcl) :-
( '$lgt_pp_dcl_'(_) ->
% local or inherited predicate declarations exist
true
; % standalone category with no local or inherited predicate declarations
'$lgt_pp_dynamic_' ->
% dynamic category; calls to the dynamic predicate implementing the
% predicate declaration table fail when there are no clauses
true
; % static category; generate a catchall clause as the predicate
% implementing the predicate declaration table is also static
functor(Head, Dcl, 5),
assertz('$lgt_pp_dcl_'((Head:-fail)))
).
'$lgt_generate_category_def_clauses'(Ctg, Def, Rnm) :-
'$lgt_generate_category_local_def_clauses'(Ctg, Def),
'$lgt_generate_category_extends_def_clauses'(Def, Rnm).
'$lgt_generate_category_local_def_clauses'(Ctg, Def) :-
'$lgt_execution_context_this_entity'(ExCtx, _, Ctg),
Head =.. [Def, Pred, ExCtx, Call, Ctg],
( '$lgt_pp_def_'(_) ->
Body =.. [Def, Pred, ExCtx, Call]
; Body = fail
),
assertz('$lgt_pp_def_'((Head:-Body))).
'$lgt_generate_category_extends_def_clauses'(Def, Rnm) :-
'$lgt_pp_extended_category_'(ExtCtg, Ctg, _, _, ExtDef, _),
'$lgt_execution_context_update_this_entity'(CExCtx, This, Ctg, EExCtx, This, ExtCtg),
Lookup =.. [ExtDef, Pred, EExCtx, Call, Ctn],
( '$lgt_pp_predicate_alias_'(ExtCtg, _, _, _, _, _) ->
Head =.. [Def, Alias, CExCtx, Call, Ctn],
Rename =.. [Rnm, ExtCtg, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [Def, Pred, CExCtx, Call, Ctn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_category_extends_def_clauses'(_, _).
% the database built-in methods need to check if a local declaration or a local definition
% exists for a predicate; in order to avoid predicate existence errors, we need to generate
% a catchall clause for static objects when there are no local predicate declarations or no
% local predicate definitions
'$lgt_generate_object_catchall_local_dcl_clause'(true, _).
'$lgt_generate_object_catchall_local_dcl_clause'(false, Dcl) :-
( '$lgt_pp_dynamic_' ->
% dynamic object; calls to the dynamic predicate implementing the
% predicate declaration table fail when there are no clauses
true
; % static object; generate a catchall clause as the predicate
% implementing the predicate declaration table is also static
functor(Head, Dcl, 4),
assertz('$lgt_pp_dcl_'((Head:-fail)))
).
'$lgt_generate_object_catchall_def_clauses'(true, _).
'$lgt_generate_object_catchall_def_clauses'(false, Def) :-
( '$lgt_pp_dynamic_' ->
% dynamic object; calls to the dynamic predicate implementing the
% predicate definition table fail when there are no clauses
true
; % static object; generate a catchall clause as the predicate
% implementing the predicate definition table is also static
functor(Head, Def, 3),
assertz('$lgt_pp_def_'((Head:-fail)))
).
'$lgt_generate_prototype_clauses' :-
'$lgt_pp_object_'(Obj, _, Dcl, Def, Super, _, _, DDcl, DDef, Rnm, _),
'$lgt_compiler_flag'(complements, Complements),
'$lgt_generate_prototype_dcl_clauses'(Obj, Dcl, DDcl, Rnm, Complements),
'$lgt_generate_prototype_def_clauses'(Obj, Def, DDef, Rnm, Complements),
'$lgt_generate_prototype_super_clauses'(Super, Rnm).
'$lgt_generate_prototype_dcl_clauses'(Obj, Dcl, DDcl, Rnm, Complements) :-
% first, generate the local table of predicate declarations:
'$lgt_generate_dcl_table_clauses'(Dcl, Local),
% second, generate linking clauses for accessing both local
% declarations and declarations in related entities (some
% linking clauses depend on the existence of local predicate
% declarations
( Complements == allow ->
% complementing categories are allowed to override local predicate declarations
'$lgt_generate_prototype_complements_dcl_clauses'(Obj, Dcl),
'$lgt_generate_prototype_local_dcl_clauses'(Local, Complements, Obj, Dcl, DDcl)
; Complements == restrict ->
% complementing categories can add to but not override local predicate declarations
'$lgt_generate_prototype_local_dcl_clauses'(Local, Complements, Obj, Dcl, DDcl),
'$lgt_generate_prototype_complements_dcl_clauses'(Obj, Dcl)
; % Complements == deny,
'$lgt_generate_prototype_local_dcl_clauses'(Local, Complements, Obj, Dcl, DDcl)
),
'$lgt_generate_prototype_implements_dcl_clauses'(Dcl, Rnm),
'$lgt_generate_prototype_imports_dcl_clauses'(Dcl, Rnm),
'$lgt_generate_prototype_extends_dcl_clauses'(Dcl, Rnm),
% third, add a catchall clause if necessary
'$lgt_generate_object_catchall_local_dcl_clause'(Local, Dcl).
'$lgt_generate_prototype_complements_dcl_clauses'(Obj, Dcl) :-
Head =.. [Dcl, Pred, Scope, Meta, Flags, SCtn, TCtn],
Lookup = '$lgt_complemented_object'(Obj, Dcl, Pred, Scope, Meta, Flags, SCtn, TCtn),
assertz('$lgt_pp_dcl_'((Head:-Lookup))).
'$lgt_generate_prototype_local_dcl_clauses'(true, _, Obj, Dcl, DDcl) :-
% there are local (compile-time) predicate declarations
HeadDcl =.. [Dcl, Pred, Scope, Meta, Flags, Obj, Obj],
BodyDcl =.. [Dcl, Pred, Scope, Meta, Flags],
% lookup access to local, static, predicate declarations
assertz('$lgt_pp_dcl_'((HeadDcl:-BodyDcl))),
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
HeadDDcl =.. [Dcl, Pred, Scope, no, 2, Obj, Obj],
BodyDDcl =.. [DDcl, Pred, Scope],
% lookup access to local, dynamic, (runtime) predicate declarations
assertz('$lgt_pp_dcl_'((HeadDDcl:-BodyDDcl)))
; true
).
'$lgt_generate_prototype_local_dcl_clauses'(false, Complements, Obj, Dcl, DDcl) :-
% no local (compile-time) predicate declarations
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
HeadDDcl =.. [Dcl, Pred, Scope, no, 2, Obj, Obj],
BodyDDcl =.. [DDcl, Pred, Scope],
% lookup access to local, dynamic, (runtime) predicate declarations
assertz('$lgt_pp_dcl_'((HeadDDcl:-BodyDDcl)))
; Complements == deny,
\+ '$lgt_pp_implemented_protocol_'(_, _, _, _, _),
\+ '$lgt_pp_imported_category_'(_, _, _, _, _, _),
\+ '$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
% standalone prototype with no access to predicate declarations
functor(HeadDDcl, Dcl, 6),
% catchall clause to avoid lookup errors
assertz('$lgt_pp_dcl_'((HeadDDcl:-fail)))
; true
).
'$lgt_generate_prototype_implements_dcl_clauses'(ODcl, Rnm) :-
'$lgt_pp_implemented_protocol_'(Ptc, Obj, _, PDcl, RelationScope),
( RelationScope == (public) ->
Lookup =.. [PDcl, Pred, Scope, Meta, Flags, TCtn]
; RelationScope == protected ->
Lookup0 =.. [PDcl, Pred, Scope2, Meta, Flags, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [PDcl, Pred, _, Meta, Flags, TCtn]
),
( '$lgt_pp_predicate_alias_'(Ptc, _, _, _, _, _) ->
Head =.. [ODcl, Alias, Scope, Meta, Flags, Obj, TCtn],
Rename =.. [Rnm, Ptc, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [ODcl, Pred, Scope, Meta, Flags, Obj, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_prototype_implements_dcl_clauses'(_, _).
'$lgt_generate_prototype_imports_dcl_clauses'(ODcl, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, CDcl, _, RelationScope),
( RelationScope == (public) ->
Lookup =.. [CDcl, Pred, Scope, Meta, Flags, TCtn]
; RelationScope == protected ->
Lookup0 =.. [CDcl, Pred, Scope2, Meta, Flags, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [CDcl, Pred, _, Meta, Flags, TCtn]
),
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [ODcl, Alias, Scope, Meta, Flags, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [ODcl, Pred, Scope, Meta, Flags, Obj, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_prototype_imports_dcl_clauses'(_, _).
'$lgt_generate_prototype_extends_dcl_clauses'(ODcl, Rnm) :-
'$lgt_pp_extended_object_'(Parent, Obj, _, PDcl, _, _, _, _, _, _, RelationScope),
( RelationScope == (public) ->
Lookup =.. [PDcl, Pred, Scope, Meta, Flags, SCtn, TCtn]
; RelationScope == protected ->
Lookup0 =.. [PDcl, Pred, Scope2, Meta, Flags, SCtn, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup0 =.. [PDcl, Pred, Scope2, Meta, Flags, SCtn2, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope_container'(Scope2, SCtn2, Obj, SCtn))
),
( '$lgt_pp_predicate_alias_'(Parent, _, _, _, _, _) ->
Head =.. [ODcl, Alias, Scope, Meta, Flags, SCtn, TCtn],
Rename =.. [Rnm, Parent, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [ODcl, Pred, Scope, Meta, Flags, SCtn, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_prototype_extends_dcl_clauses'(_, _).
'$lgt_generate_prototype_def_clauses'(Obj, Def, DDef, Rnm, Complements) :-
% some linking clauses depend on the existence of local predicate definitions
( '$lgt_pp_def_'(_) ->
Local = true
; Local = false
),
( Complements == allow ->
% complementing categories are allowed to override local predicate definitions
'$lgt_generate_prototype_complements_def_clauses'(Obj, Def),
'$lgt_generate_prototype_local_def_clauses'(Local, Obj, Def, DDef)
; Complements == restrict ->
% complementing categories can add to but not override local predicate definitions
'$lgt_generate_prototype_local_def_clauses'(Local, Obj, Def, DDef),
'$lgt_generate_prototype_complements_def_clauses'(Obj, Def)
; % Complements == deny,
'$lgt_generate_prototype_local_def_clauses'(Local, Obj, Def, DDef)
),
'$lgt_generate_prototype_imports_def_clauses'(Def, Rnm),
'$lgt_generate_prototype_extends_def_clauses'(Def, Rnm),
% add a catchall clause if necessary
'$lgt_generate_object_catchall_def_clauses'(Local, Def).
'$lgt_generate_prototype_complements_def_clauses'(Obj, Def) :-
Head =.. [Def, Pred, ExCtx, Call, Obj, TCtn],
Lookup = '$lgt_complemented_object'(Obj, Def, Pred, ExCtx, Call, TCtn),
assertz('$lgt_pp_def_'((Head:-Lookup))).
'$lgt_generate_prototype_local_def_clauses'(true, Obj, Def, DDef) :-
% there are local (compile-time) predicate definitions
'$lgt_execution_context_this_entity'(ExCtx, Obj, Obj),
Head =.. [Def, Pred, ExCtx, Call, Obj, Obj],
BodyDef =.. [Def, Pred, ExCtx, Call],
% lookup access to local, static, predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDef))),
BodyDDef =.. [DDef, Pred, ExCtx, Call],
% lookup access to local, dynamic, (runtime) predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDDef))).
'$lgt_generate_prototype_local_def_clauses'(false, Obj, Def, DDef) :-
% no local (compile-time) predicate definitions
'$lgt_execution_context_this_entity'(ExCtx, Obj, Obj),
Head =.. [Def, Pred, ExCtx, Call, Obj, Obj],
BodyDDef =.. [DDef, Pred, ExCtx, Call],
% lookup access to local, dynamic, (runtime) predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDDef))).
'$lgt_generate_prototype_imports_def_clauses'(ODef, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, _, CDef, _),
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, CExCtx, Obj, Ctg),
Lookup =.. [CDef, Pred, CExCtx, Call, TCtn],
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [ODef, Alias, OExCtx, Call, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [ODef, Pred, OExCtx, Call, Obj, TCtn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_prototype_imports_def_clauses'(_, _).
'$lgt_generate_prototype_extends_def_clauses'(ODef, Rnm) :-
'$lgt_pp_extended_object_'(Parent, Obj, _, _, PDef, _, _, _, _, _, _),
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, PExCtx, Parent, Parent),
Lookup =.. [PDef, Pred, PExCtx, Call, SCtn, TCtn],
( '$lgt_pp_predicate_alias_'(Parent, _, _, _, _, _) ->
Head =.. [ODef, Alias, OExCtx, Call, SCtn, TCtn],
Rename =.. [Rnm, Parent, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [ODef, Pred, OExCtx, Call, SCtn, TCtn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_prototype_extends_def_clauses'(_, _).
% we can have a root object where super have nowhere to go ...
'$lgt_generate_prototype_super_clauses'(Super, _) :-
\+ '$lgt_pp_imported_category_'(_, _, _, _, _, _),
\+ '$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _),
functor(Head, Super, 5),
assertz('$lgt_pp_super_'((Head:-fail))),
!.
% ... or we may import some categories
'$lgt_generate_prototype_super_clauses'(Super, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, _, CDef, _),
% the entity in the object execution context is usually the object itself
% but it can also be a complementing category; thus, the argument must be
% left uninstantiated but it will be bound by the runtime
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, _, CExCtx, Obj, Ctg),
Lookup =.. [CDef, Pred, CExCtx, Call, TCtn],
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [Super, Alias, OExCtx, Call, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_super_'((Head :- Rename, Lookup)))
; Head =.. [Super, Pred, OExCtx, Call, Obj, TCtn],
assertz('$lgt_pp_super_'((Head:-Lookup)))
),
fail.
% ... or we may extend some objects
'$lgt_generate_prototype_super_clauses'(Super, Rnm) :-
'$lgt_pp_extended_object_'(Parent, Obj, _, _, PDef, _, _, _, _, _, _),
% the entity in the object execution context is usually the object itself
% but it can also be a complementing category; thus, the argument must be
% left uninstantiated but it will be bound by the runtime
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, _, PExCtx, Parent, Parent),
Lookup =.. [PDef, Pred, PExCtx, Call, SCtn, TCtn],
( '$lgt_pp_predicate_alias_'(Parent, _, _, _, _, _) ->
Head =.. [Super, Alias, OExCtx, Call, SCtn, TCtn],
Rename =.. [Rnm, Parent, Pred, Alias],
assertz('$lgt_pp_super_'((Head :- Rename, Lookup)))
; Head =.. [Super, Pred, OExCtx, Call, SCtn, TCtn],
assertz('$lgt_pp_super_'((Head:-Lookup)))
),
fail.
'$lgt_generate_prototype_super_clauses'(_, _).
'$lgt_generate_ic_clauses' :-
'$lgt_pp_object_'(Obj, _, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, _),
'$lgt_compiler_flag'(complements, Complements),
'$lgt_generate_ic_dcl_clauses'(Obj, Dcl, IDcl, DDcl, Rnm, Complements),
'$lgt_generate_ic_def_clauses'(Obj, Def, IDef, DDef, Rnm, Complements),
'$lgt_generate_ic_super_clauses'(Obj, Super, Rnm).
'$lgt_generate_ic_dcl_clauses'(Obj, Dcl, IDcl, DDcl, Rnm, Complements) :-
% first, generate the local table of predicate declarations:
'$lgt_generate_dcl_table_clauses'(Dcl, Local),
% second, generate linking clauses for accessing declarations
% in related entities (for an instance, the lookup for a predicate
% declaration always start at its classes)
'$lgt_generate_ic_instantiates_dcl_clauses'(Dcl, Rnm),
% third, add a catchall clause if necessary
'$lgt_generate_object_catchall_local_dcl_clause'(Local, Dcl),
% finaly, generate linking clauses for accessing declarations
% when we reach the class being compiled during a lookup
% from a descendant instance
'$lgt_generate_ic_idcl_clauses'(Local, Obj, Dcl, IDcl, DDcl, Rnm, Complements).
'$lgt_generate_ic_instantiates_dcl_clauses'(ODcl, _) :-
\+ '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _),
% no meta-class for the class we're compiling
!,
functor(Head, ODcl, 6),
assertz('$lgt_pp_dcl_'((Head:-fail))).
'$lgt_generate_ic_instantiates_dcl_clauses'(ODcl, Rnm) :-
'$lgt_pp_instantiated_class_'(Class, Obj, _, _, _, _, CIDcl, _, _, _, RelationScope),
( RelationScope == (public) ->
Lookup =.. [CIDcl, Pred, Scope, Meta, Flags, SCtn, TCtn]
; RelationScope == protected ->
Lookup0 =.. [CIDcl, Pred, Scope2, Meta, Flags, SCtn, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup0 =.. [CIDcl, Pred, Scope2, Meta, Flags, SCtn2, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope_container'(Scope2, SCtn2, Obj, SCtn))
),
( '$lgt_pp_predicate_alias_'(Class, _, _, _, _, _) ->
Head =.. [ODcl, Alias, Scope, Meta, Flags, SCtn, TCtn],
Rename =.. [Rnm, Class, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [ODcl, Pred, Scope, Meta, Flags, SCtn, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_instantiates_dcl_clauses'(_, _).
% generates the declaration linking clauses that are used
% when traversing specialization links in order to lookup
% a predicate declaration for a descendant instance
'$lgt_generate_ic_idcl_clauses'(Local, Obj, Dcl, IDcl, DDcl, Rnm, Complements) :-
% generate linking clauses for accessing declarations in related entities
( Complements == allow ->
% complementing categories are allowed to override local predicate declarations
'$lgt_generate_ic_complements_idcl_clauses'(Obj, IDcl),
'$lgt_generate_ic_local_idcl_clauses'(Local, Complements, Obj, Dcl, IDcl, DDcl)
; Complements == restrict ->
% complementing categories can add to but not override local predicate declarations
'$lgt_generate_ic_local_idcl_clauses'(Local, Complements, Obj, Dcl, IDcl, DDcl),
'$lgt_generate_ic_complements_idcl_clauses'(Obj, IDcl)
; % Complements == deny,
'$lgt_generate_ic_local_idcl_clauses'(Local, Complements, Obj, Dcl, IDcl, DDcl)
),
'$lgt_generate_ic_implements_idcl_clauses'(IDcl, Rnm),
'$lgt_generate_ic_imports_idcl_clauses'(IDcl, Rnm),
'$lgt_generate_ic_specializes_idcl_clauses'(IDcl, Rnm).
'$lgt_generate_ic_complements_idcl_clauses'(Obj, IDcl) :-
Head =.. [IDcl, Pred, Scope, Meta, Flags, SCtn, TCtn],
Lookup = '$lgt_complemented_object'(Obj, IDcl, Pred, Scope, Meta, Flags, SCtn, TCtn),
assertz('$lgt_pp_dcl_'((Head:-Lookup))).
'$lgt_generate_ic_local_idcl_clauses'(true, _, Obj, Dcl, IDcl, DDcl) :-
% there are local (compile-time) predicate declarations
HeadDcl =.. [IDcl, Pred, Scope, Meta, Flags, Obj, Obj],
BodyDcl =.. [Dcl, Pred, Scope, Meta, Flags],
% lookup access to local, static, predicate declarations
assertz('$lgt_pp_dcl_'((HeadDcl:-BodyDcl))),
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
HeadDDcl =.. [IDcl, Pred, Scope, no, 2, Obj, Obj],
BodyDDcl =.. [DDcl, Pred, Scope],
% lookup access to local, dynamic, (runtime) predicate declarations
assertz('$lgt_pp_dcl_'((HeadDDcl:-BodyDDcl)))
; true
).
'$lgt_generate_ic_local_idcl_clauses'(false, Complements, Obj, _, IDcl, DDcl) :-
% no local (compile-time) predicate declarations
( '$lgt_compiler_flag'(dynamic_declarations, allow) ->
HeadDDcl =.. [IDcl, Pred, Scope, no, 2, Obj, Obj],
BodyDDcl =.. [DDcl, Pred, Scope],
% lookup access to local, dynamic, (runtime) predicate declarations
assertz('$lgt_pp_dcl_'((HeadDDcl:-BodyDDcl)))
; Complements == deny,
\+ '$lgt_pp_implemented_protocol_'(_, _, _, _, _),
\+ '$lgt_pp_imported_category_'(_, _, _, _, _, _),
\+ '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
% standalone class with no access to predicate declarations
functor(HeadDDcl, IDcl, 6),
% catchall clause to avoid lookup errors
assertz('$lgt_pp_dcl_'((HeadDDcl:-fail)))
; true
).
'$lgt_generate_ic_implements_idcl_clauses'(OIDcl, Rnm) :-
'$lgt_pp_implemented_protocol_'(Ptc, Obj, _, PDcl, RelationScope),
( RelationScope == (public) ->
Lookup =.. [PDcl, Pred, Scope, Meta, Flags, TCtn]
; RelationScope == protected ->
Lookup0 =.. [PDcl, Pred, Scope2, Meta, Flags, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [PDcl, Pred, _, Meta, Flags, TCtn]
),
( '$lgt_pp_predicate_alias_'(Ptc, _, _, _, _, _) ->
Head =.. [OIDcl, Alias, Scope, Meta, Flags, Obj, TCtn],
Rename =.. [Rnm, Ptc, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [OIDcl, Pred, Scope, Meta, Flags, Obj, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_implements_idcl_clauses'(_, _).
'$lgt_generate_ic_imports_idcl_clauses'(OIDcl, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, CDcl, _, RelationScope),
( RelationScope == (public) ->
Lookup =.. [CDcl, Pred, Scope, Meta, Flags, TCtn]
; RelationScope == protected ->
Lookup0 =.. [CDcl, Pred, Scope2, Meta, Flags, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup =.. [CDcl, Pred, _, Meta, Flags, TCtn]
),
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [OIDcl, Alias, Scope, Meta, Flags, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [OIDcl, Pred, Scope, Meta, Flags, Obj, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_imports_idcl_clauses'(_, _).
'$lgt_generate_ic_specializes_idcl_clauses'(CIDcl, Rnm) :-
'$lgt_pp_specialized_class_'(Super, Obj, _, _, _, _, SIDcl, _, _, _, RelationScope),
( RelationScope == (public) ->
Lookup =.. [SIDcl, Pred, Scope, Meta, Flags, SCtn, TCtn]
; RelationScope == protected ->
Lookup0 =.. [SIDcl, Pred, Scope2, Meta, Flags, SCtn, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope'(Scope2, Scope))
; Scope = p,
Lookup0 =.. [SIDcl, Pred, Scope2, Meta, Flags, SCtn2, TCtn],
Lookup = (Lookup0, '$lgt_filter_scope_container'(Scope2, SCtn2, Obj, SCtn))
),
( '$lgt_pp_predicate_alias_'(Super, _, _, _, _, _) ->
Head =.. [CIDcl, Alias, Scope, Meta, Flags, SCtn, TCtn],
Rename =.. [Rnm, Super, Pred, Alias],
assertz('$lgt_pp_dcl_'((Head :- Rename, Lookup)))
; Head =.. [CIDcl, Pred, Scope, Meta, Flags, SCtn, TCtn],
assertz('$lgt_pp_dcl_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_specializes_idcl_clauses'(_, _).
% lookup of predicate definitions start at the instance itself
% (not at its classes as it's the case for predicate declarations)
'$lgt_generate_ic_def_clauses'(Obj, Def, IDef, DDef, Rnm, Complements) :-
% some linking clauses depend on the existence of local predicate definitions
( '$lgt_pp_def_'(_) ->
Local = true
; Local = false
),
( Complements == allow ->
% complementing categories are allowed to override local predicate definitions
'$lgt_generate_ic_complements_def_clauses'(Obj, Def),
'$lgt_generate_ic_local_def_clauses'(Local, Obj, Def, DDef)
; Complements == restrict ->
% complementing categories can add to but not override local predicate definitions
'$lgt_generate_ic_local_def_clauses'(Local, Obj, Def, DDef),
'$lgt_generate_ic_complements_def_clauses'(Obj, Def)
; % Complements == deny,
'$lgt_generate_ic_local_def_clauses'(Local, Obj, Def, DDef)
),
'$lgt_generate_ic_imports_def_clauses'(Def, Rnm),
'$lgt_generate_ic_instantiates_def_clauses'(Def, Rnm),
% add a catchall clause if necessary
'$lgt_generate_object_catchall_def_clauses'(Local, Def),
% generate linking clauses for accessing definitions when
% we reach the class being compiled during a lookup from
% a descendant instance
'$lgt_generate_ic_idef_clauses'(Local, Obj, Def, IDef, DDef, Rnm, Complements).
'$lgt_generate_ic_complements_def_clauses'(Obj, Def) :-
Head =.. [Def, Pred, ExCtx, Call, Obj, TCtn],
Lookup = '$lgt_complemented_object'(Obj, Def, Pred, ExCtx, Call, TCtn),
assertz('$lgt_pp_def_'((Head:-Lookup))).
'$lgt_generate_ic_local_def_clauses'(true, Obj, Def, DDef) :-
% there are local (compile-time) predicate definitions
'$lgt_execution_context_this_entity'(ExCtx, Obj, Obj),
Head =.. [Def, Pred, ExCtx, Call, Obj, Obj],
BodyDef =.. [Def, Pred, ExCtx, Call],
% lookup access to local, static, predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDef))),
BodyDDef =.. [DDef, Pred, ExCtx, Call],
% lookup access to local, dynamic, (runtime) predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDDef))).
'$lgt_generate_ic_local_def_clauses'(false, Obj, Def, DDef) :-
% no local (compile-time) predicate definitions
'$lgt_execution_context_this_entity'(ExCtx, Obj, Obj),
Head =.. [Def, Pred, ExCtx, Call, Obj, Obj],
BodyDDef =.. [DDef, Pred, ExCtx, Call],
% lookup access to local, dynamic, (runtime) predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDDef))).
'$lgt_generate_ic_imports_def_clauses'(ODef, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, _, CDef, _),
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, CExCtx, Obj, Ctg),
Lookup =.. [CDef, Pred, CExCtx, Call, TCtn],
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [ODef, Alias, OExCtx, Call, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [ODef, Pred, OExCtx, Call, Obj, TCtn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_imports_def_clauses'(_, _).
'$lgt_generate_ic_instantiates_def_clauses'(ODef, Rnm) :-
'$lgt_pp_instantiated_class_'(Class, Obj, _, _, _, _, _, CIDef, _, _, _),
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, CExCtx, Class, Class),
Lookup =.. [CIDef, Pred, CExCtx, Call, SCtn, TCtn],
( '$lgt_pp_predicate_alias_'(Class, _, _, _, _, _) ->
Head =.. [ODef, Alias, OExCtx, Call, SCtn, TCtn],
Rename =.. [Rnm, Class, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [ODef, Pred, OExCtx, Call, SCtn, TCtn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_instantiates_def_clauses'(_, _).
% generates the definition linking clauses that are used
% when traversing specialization links in order to lookup
% a predicate definition for a descendant instance
'$lgt_generate_ic_idef_clauses'(Local, Obj, Def, IDef, DDef, Rnm, Complements) :-
( Complements == allow ->
% complementing categories are allowed to override local predicate definitions
'$lgt_generate_ic_complements_idef_clauses'(Obj, IDef),
'$lgt_generate_ic_local_idef_clauses'(Local, Obj, Def, IDef, DDef)
; Complements == restrict ->
% complementing categories can add to but not override local predicate definitions
'$lgt_generate_ic_local_idef_clauses'(Local, Obj, Def, IDef, DDef),
'$lgt_generate_ic_complements_idef_clauses'(Obj, IDef)
; % Complements == deny,
'$lgt_generate_ic_local_idef_clauses'(Local, Obj, Def, IDef, DDef)
),
'$lgt_generate_ic_complements_idef_clauses'(Obj, IDef),
'$lgt_generate_ic_local_idef_clauses'(Local, Obj, Def, IDef, DDef),
'$lgt_generate_ic_imports_idef_clauses'(IDef, Rnm),
'$lgt_generate_ic_specializes_idef_clauses'(IDef, Rnm).
'$lgt_generate_ic_complements_idef_clauses'(Obj, IDef) :-
Head =.. [IDef, Pred, ExCtx, Call, Obj, TCtn],
Lookup = '$lgt_complemented_object'(Obj, IDef, Pred, ExCtx, Call, TCtn),
assertz('$lgt_pp_def_'((Head:-Lookup))).
'$lgt_generate_ic_local_idef_clauses'(true, Obj, Def, IDef, DDef) :-
% there are local (compile-time) predicate definitions
'$lgt_execution_context_this_entity'(ExCtx, Obj, Obj),
Head =.. [IDef, Pred, ExCtx, Call, Obj, Obj],
BodyDef =.. [Def, Pred, ExCtx, Call],
% lookup access to local, static, predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDef))),
BodyDDef =.. [DDef, Pred, ExCtx, Call],
% lookup access to local, dynamic, (runtime) predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDDef))).
'$lgt_generate_ic_local_idef_clauses'(false, Obj, _, IDef, DDef) :-
% no local (compile-time) predicate definitions
'$lgt_execution_context_this_entity'(ExCtx, Obj, Obj),
Head =.. [IDef, Pred, ExCtx, Call, Obj, Obj],
BodyDDef =.. [DDef, Pred, ExCtx, Call],
% lookup access to local, dynamic, (runtime) predicate definitions
assertz('$lgt_pp_def_'((Head:-BodyDDef))).
'$lgt_generate_ic_imports_idef_clauses'(OIDef, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, _, CDef, _),
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, CExCtx, Obj, Ctg),
Lookup =.. [CDef, Pred, CExCtx, Call, TCtn],
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [OIDef, Alias, OExCtx, Call, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [OIDef, Pred, OExCtx, Call, Obj, TCtn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_imports_idef_clauses'(_, _).
'$lgt_generate_ic_specializes_idef_clauses'(CIDef, Rnm) :-
'$lgt_pp_specialized_class_'(Super, Class, _, _, _, _, _, SIDef, _, _, _),
'$lgt_execution_context_update_this_entity'(CExCtx, Class, Class, SExCtx, Super, Super),
Lookup =.. [SIDef, Pred, SExCtx, Call, SCtn, TCtn],
( '$lgt_pp_predicate_alias_'(Super, _, _, _, _, _) ->
Head =.. [CIDef, Alias, CExCtx, Call, SCtn, TCtn],
Rename =.. [Rnm, Super, Pred, Alias],
assertz('$lgt_pp_def_'((Head :- Rename, Lookup)))
; Head =.. [CIDef, Pred, CExCtx, Call, SCtn, TCtn],
assertz('$lgt_pp_def_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_specializes_idef_clauses'(_, _).
% we can have a root object where "super" have nowhere to go ...
'$lgt_generate_ic_super_clauses'(Obj, Super, _) :-
\+ '$lgt_pp_imported_category_'(_, _, _, _, _, _),
\+ '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _),
\+ ('$lgt_pp_instantiated_class_'(Class, _, _, _, _, _, _, _, _, _, _), Class \= Obj),
functor(Head, Super, 5),
assertz('$lgt_pp_super_'((Head:-fail))),
!.
% ... or we may import some categories
'$lgt_generate_ic_super_clauses'(Obj, Super, Rnm) :-
'$lgt_pp_imported_category_'(Ctg, Obj, _, _, CDef, _),
% the entity in the object execution context is usually the object itself
% but it can also be a complementing category; thus, the argument must be
% left uninstantiated but it will be bound by the runtime
'$lgt_execution_context_update_this_entity'(OExCtx, _, Obj, CExCtx, Obj, Ctg),
Lookup =.. [CDef, Pred, CExCtx, Call, TCtn],
( '$lgt_pp_predicate_alias_'(Ctg, _, _, _, _, _) ->
Head =.. [Super, Alias, OExCtx, Call, Obj, TCtn],
Rename =.. [Rnm, Ctg, Pred, Alias],
assertz('$lgt_pp_super_'((Head :- Rename, Lookup)))
; Head =.. [Super, Pred, OExCtx, Call, Obj, TCtn],
assertz('$lgt_pp_super_'((Head:-Lookup)))
),
fail.
% ... or predicates can be redefined in instances...
'$lgt_generate_ic_super_clauses'(Obj, Super, Rnm) :-
'$lgt_pp_instantiated_class_'(Class, Obj, _, _, _, _, _, CIDef, _, _, _),
% we can ignore class self-instantiation, which is often used in reflective designs
Class \= Obj,
% the entity in the object execution context is usually the object itself
% but it can also be a complementing category; thus, the argument must be
% left uninstantiated but it will be bound by the runtime
'$lgt_execution_context_update_this_entity'(OExCtx, _, Obj, CExCtx, Class, Class),
Lookup =.. [CIDef, Pred, CExCtx, Call, SCtn, TCtn],
% the following restriction allows us to distinguish the two "super" clauses that
% are generated when an object both instantiates and specializes other objects
'$lgt_execution_context'(OExCtx, _, _, Obj, Obj, _, _),
( '$lgt_pp_predicate_alias_'(Class, _, _, _, _, _) ->
Head =.. [Super, Alias, OExCtx, Call, SCtn, TCtn],
Rename =.. [Rnm, Class, Pred, Alias],
assertz('$lgt_pp_super_'((Head :- Rename, Lookup)))
; Head =.. [Super, Pred, OExCtx, Call, SCtn, TCtn],
assertz('$lgt_pp_super_'((Head:-Lookup)))
),
fail.
% ... or/and in subclasses...
'$lgt_generate_ic_super_clauses'(Class, Super, Rnm) :-
'$lgt_pp_specialized_class_'(Superclass, Class, _, _, _, _, _, SIDef, _, _, _),
% the entity in the object execution context is usually the class itself
% but it can also be a complementing category; thus, the argument must be
% left uninstantiated but it will be bound by the runtime
'$lgt_execution_context_update_this_entity'(CExCtx, _, Class, SExCtx, Superclass, Superclass),
Lookup =.. [SIDef, Pred, SExCtx, Call, SCtn, TCtn],
( '$lgt_pp_predicate_alias_'(Superclass, _, _, _, _, _) ->
Head =.. [Super, Alias, CExCtx, Call, SCtn, TCtn],
Rename =.. [Rnm, Superclass, Pred, Alias],
assertz('$lgt_pp_super_'((Head :- Rename, Lookup)))
; Head =.. [Super, Pred, CExCtx, Call, SCtn, TCtn],
assertz('$lgt_pp_super_'((Head:-Lookup)))
),
fail.
'$lgt_generate_ic_super_clauses'(_, _, _).
% '$lgt_compile_predicate_calls'(+atom)
%
% compiles predicate calls in entity clause rules and in initialization goals
%
% all predicate calls are compiled on this compiler second stage to take advantage
% of the information about declared and defined predicates collected on the first
% stage, thus making predicate declaration and definition order irrelevant; this
% allows us to deal with e.g. meta-predicate directives and redefined built-in
% predicates which may be textually defined in an entity after their calls
'$lgt_compile_predicate_calls'(runtime) :-
% avoid querying the optimize flag for each compiled term
'$lgt_compiler_flag'(optimize, Optimize),
'$lgt_compile_predicate_calls_loop'(silent, Optimize).
'$lgt_compile_predicate_calls'(compile_time) :-
% avoid querying the duplicated_clauses and optimize flags for each compiled term
'$lgt_compiler_flag'(duplicated_clauses, DuplicatedClauses),
'$lgt_compiler_flag'(optimize, Optimize),
'$lgt_compile_predicate_calls_loop'(DuplicatedClauses, Optimize).
% compilation of auxiliary clauses can result in the
% creation of e.g. new auxiliary clauses or directives
'$lgt_compile_predicate_calls_loop'(DuplicatedClauses, Optimize) :-
'$lgt_compile_predicate_calls'(DuplicatedClauses, Optimize),
fail.
'$lgt_compile_predicate_calls_loop'(DuplicatedClauses, Optimize) :-
( ( '$lgt_pp_entity_aux_clause_'(_)
; '$lgt_pp_coinductive_'(_, _, _, _, _, _, _, _, _)
; '$lgt_pp_object_initialization_'(_, _, _)
; '$lgt_pp_entity_meta_directive_'(_, _, _)
) ->
'$lgt_compile_predicate_calls_loop'(DuplicatedClauses, Optimize)
; true
).
'$lgt_compile_predicate_calls'(warning, Optimize) :-
% user-defined terms; as SourceData may be nil, we cannot perform the
% unification in the retract/1 goal otherwise we could skip terms
retract('$lgt_pp_entity_term_'(Term, SourceData, _)),
( SourceData = sd(Original, _, _, OriginalFile, OriginalLines),
% exclude directives
Original \= (:- _),
'$lgt_pp_entity_'(Type, Entity, _),
'$lgt_internal_term_template'(Term, Template),
'$lgt_pp_entity_term_'(Template, sd(Duplicate, _, _, File, Lines), _),
'$lgt_variant'(Original, Duplicate) ->
'$lgt_increment_compiling_warnings_counter',
( Original = (_ --> _) ->
'$lgt_print_message'(
warning(duplicated_clauses),
duplicated_grammar_rule(File, Lines, Type, Entity, Original, OriginalFile, OriginalLines)
)
; '$lgt_print_message'(
warning(duplicated_clauses),
duplicated_clause(File, Lines, Type, Entity, Original, OriginalFile, OriginalLines)
)
)
; true
),
'$lgt_compile_predicate_calls'(Term, SourceData, Optimize, TTerm),
assertz('$lgt_pp_final_entity_term_'(TTerm, Lines)),
fail.
'$lgt_compile_predicate_calls'(silent, Optimize) :-
% user-defined terms
retract('$lgt_pp_entity_term_'(Term, SourceData, Lines)),
'$lgt_compile_predicate_calls'(Term, SourceData, Optimize, TTerm),
assertz('$lgt_pp_final_entity_term_'(TTerm, Lines)),
fail.
'$lgt_compile_predicate_calls'(_, _) :-
retract('$lgt_pp_coinductive_'(Head, TestHead, HeadExCtx, TCHead, BodyExCtx, THead, DHead, _, _)),
'$lgt_pp_defines_predicate_'(Head, _, _, _, _, _),
'$lgt_add_coinductive_predicate_aux_clause'(Head, TestHead, HeadExCtx, TCHead, BodyExCtx, THead, DHead),
fail.
'$lgt_compile_predicate_calls'(_, Optimize) :-
% other auxiliary clauses
retract('$lgt_pp_entity_aux_clause_'(Clause)),
'$lgt_compile_predicate_calls'(Clause, nil, Optimize, TClause),
assertz('$lgt_pp_final_entity_aux_clause_'(TClause)),
fail.
'$lgt_compile_predicate_calls'(_, Optimize) :-
% initialization/1 goals
retract('$lgt_pp_object_initialization_'(Goal, SourceData, Lines)),
'$lgt_compile_predicate_calls'(Goal, SourceData, Optimize, TGoal),
assertz('$lgt_pp_final_object_initialization_'(TGoal, Lines)),
fail.
'$lgt_compile_predicate_calls'(_, Optimize) :-
% other initialization goals found on proprietary Prolog directives
retract('$lgt_pp_entity_meta_directive_'(Directive, SourceData, _)),
'$lgt_compile_predicate_calls'(Directive, SourceData, Optimize, TDirective),
assertz('$lgt_pp_directive_'(TDirective)),
fail.
'$lgt_compile_predicate_calls'(_, _).
% auxiliary predicate used when checking for duplicated clauses
'$lgt_internal_term_template'(srule(_,_,_), srule(_,_,_)).
'$lgt_internal_term_template'(dsrule(_,_,_,_), dsrule(_,_,_,_)).
'$lgt_internal_term_template'(drule(_,_,_,_), drule(_,_,_,_)).
'$lgt_internal_term_template'(ddrule(_,_,_,_,_), ddrule(_,_,_,_,_)).
'$lgt_internal_term_template'(fact(_,_), fact(_,_)).
'$lgt_internal_term_template'(dfact(_,_,_), dfact(_,_,_)).
% '$lgt_compile_predicate_calls'(+callable, +compound, +atom, -callable)
% entity term is final
'$lgt_compile_predicate_calls'({Term}, _, _, Term).
'$lgt_compile_predicate_calls'(fact(TFact,_), _, _, TFact).
% debug version of a predicate fact
'$lgt_compile_predicate_calls'(dfact(TFact,DHead,_), _, _, (TFact:-DHead)).
% static predicate rule
'$lgt_compile_predicate_calls'(srule(THead,Body,Ctx), SourceData, Optimize, TClause) :-
'$lgt_add_source_data'(SourceData),
catch(
'$lgt_compile_body'(Body, rule, FBody, _, Ctx),
Error,
('$lgt_comp_ctx_head'(Ctx,Head), throw(error(Error,clause((Head:-Body)))))
),
( Optimize == on ->
'$lgt_simplify_goal'(FBody, SBody)
; SBody = FBody
),
( SBody == true ->
TClause = THead
; TClause = (THead:-SBody)
).
% debug version of static predicate rule
'$lgt_compile_predicate_calls'(dsrule(THead,DHead,Body,Ctx), SourceData, _, (THead:-DHead,DBody)) :-
'$lgt_add_source_data'(SourceData),
catch(
'$lgt_compile_body'(Body, rule, _, DBody, Ctx),
Error,
('$lgt_comp_ctx_head'(Ctx,Head), throw(error(Error,clause((Head:-Body)))))
).
% dynamic predicate rule
'$lgt_compile_predicate_calls'(drule(THead,Nop,Body,Ctx), SourceData, Optimize, TClause) :-
'$lgt_add_source_data'(SourceData),
catch(
'$lgt_compile_body'(Body, rule, TBody0, _, Ctx),
Error,
('$lgt_comp_ctx_head'(Ctx,Head), throw(error(Error,clause((Head:-Body)))))
),
( Optimize == on ->
'$lgt_simplify_goal'(TBody0, TBody)
; TBody = TBody0
),
( TBody == true ->
TClause = (THead:-Nop)
; TClause = (THead:-Nop,TBody)
).
% debug version of dynamic predicate rule
'$lgt_compile_predicate_calls'(ddrule(THead,Nop,DHead,Body,Ctx), SourceData, _, (THead:-Nop,DHead,DBody)) :-
'$lgt_add_source_data'(SourceData),
catch(
'$lgt_compile_body'(Body, rule, _, DBody, Ctx),
Error,
('$lgt_comp_ctx_head'(Ctx,Head), throw(error(Error,clause((Head:-Body)))))
).
% initialization goal
'$lgt_compile_predicate_calls'(goal(Body,Ctx), SourceData, Optimize, TBody) :-
'$lgt_add_source_data'(SourceData),
catch(
'$lgt_compile_body'(Body, directive, TBody0, _, Ctx),
Error,
throw(error(Error, directive(initialization(Body))))
),
( Optimize == on ->
'$lgt_simplify_goal'(TBody0, TBody)
; TBody = TBody0
).
% debug version of initialization goal
'$lgt_compile_predicate_calls'(dgoal(Body,Ctx), SourceData, _, DBody) :-
'$lgt_add_source_data'(SourceData),
catch(
'$lgt_compile_body'(Body, directive, _, DBody, Ctx),
Error,
throw(error(Error, directive(initialization(Body))))
).
% supported Prolog meta-directives (specified in the adapter files)
'$lgt_compile_predicate_calls'(directive(Directive,Meta), SourceData, _, TDirective) :-
'$lgt_add_source_data'(SourceData),
Directive =.. [Functor| Args],
Meta =.. [Functor| MArgs],
'$lgt_pp_entity_'(_, Entity, Prefix),
% MetaVars = [] as we're compiling a local call
'$lgt_comp_ctx'(Ctx, _, _, Entity, Entity, Entity, Entity, Prefix, [], _, _, _, [], _, _),
( catch(
'$lgt_compile_prolog_meta_arguments'(Args, MArgs, meta, Ctx, TArgs, DArgs),
Error,
throw(error(Error, directive(Directive)))
) ->
( '$lgt_compiler_flag'(debug, on) ->
TDirective =.. [Functor| DArgs]
; TDirective =.. [Functor| TArgs]
)
; % the meta-directive template is not usable, report it as an error
throw(error(domain_error(meta_directive_template, Meta), directive(Directive)))
).
'$lgt_add_source_data'(nil) :-
retractall('$lgt_pp_term_source_data_'(_, _, _, _, _)).
'$lgt_add_source_data'(sd(Term, VariableNames, Singletons, File, Lines)) :-
retractall('$lgt_pp_term_source_data_'(_, _, _, _, _)),
assertz('$lgt_pp_term_source_data_'(Term, VariableNames, Singletons, File, Lines)).
'$lgt_add_coinductive_predicate_aux_clause'(Head, TestHead, HeadExCtx, TCHead, BodyExCtx, THead, DHead) :-
'$lgt_execution_context'(HeadExCtx, Entity, Sender, This, Self, MetaCallCtx, HeadStack),
'$lgt_execution_context'(BodyExCtx, Entity, Sender, This, Self, MetaCallCtx, BodyStack),
'$lgt_coinductive_success_hook'(Head, Hypothesis, HeadExCtx, HeadStack, BodyStack, Hook),
( '$lgt_compiler_flag'(debug, on) ->
Header = '$lgt_debug'(rule(Entity, DHead, 0, nil, 0), BodyExCtx),
If = '$lgt_debug'(goal(check_coinductive_success(TestHead, HeadStack), '$lgt_check_coinductive_success'(TestHead, HeadStack, Hypothesis)), BodyExCtx),
Then = '$lgt_debug'(goal(coinductive_success_hook(Head, Hypothesis), Hook), BodyExCtx),
Else = (
'$lgt_debug'(goal(push_coinductive_hypothesis(TestHead, HeadStack, BodyStack), BodyStack = [Head| HeadStack]), BodyExCtx),
'$lgt_debug'(goal(Head, THead), BodyExCtx)
)
; Header = true,
If = '$lgt_check_coinductive_success'(TestHead, HeadStack, Hypothesis),
Then = Hook,
Else = (BodyStack = [Head| HeadStack], THead)
),
( '$lgt_prolog_built_in_predicate'('*->'(_, _)) ->
% backend Prolog compiler supports the soft-cut control construct
assertz('$lgt_pp_entity_aux_clause_'({(TCHead :- Header, ('*->'(If, Then); Else))}))
; '$lgt_prolog_built_in_predicate'(if(_, _, _)) ->
% backend Prolog compiler supports the if/3 soft-cut built-in meta-predicate
assertz('$lgt_pp_entity_aux_clause_'({(TCHead :- Header, if(If, Then, Else))}))
; % the adapter file for the backend Prolog compiler declares that coinduction
% is supported but it seems to be missing the necessary declaration for the
% soft-cut control construct or meta-predicate
throw(resource_error(soft_cut_support))
).
'$lgt_coinductive_success_hook'(Head, Hypothesis, ExCtx, HeadStack, BodyStack, Hook) :-
% ensure zero performance penalties when defining coinductive predicates without a definition
% for the coinductive success hook predicates
( '$lgt_pp_defines_predicate_'(coinductive_success_hook(Head,Hypothesis), _, ExCtx, THead, _, _),
\+ \+ (
'$lgt_pp_final_entity_term_'(THead, _)
; '$lgt_pp_final_entity_term_'((THead :- _), _)
) ->
% ... with at least one clause for this particular coinductive predicate head
Hook = ((HeadStack = BodyStack), THead)
; % we only consider coinductive_success_hook/1 clauses if no coinductive_success_hook/2 clause applies
'$lgt_pp_defines_predicate_'(coinductive_success_hook(Head), _, ExCtx, THead, _, _),
\+ \+ (
'$lgt_pp_final_entity_term_'(THead, _)
; '$lgt_pp_final_entity_term_'((THead :- _), _)
) ->
% ... with at least one clause for this particular coinductive predicate head
Hook = ((HeadStack = BodyStack), THead)
; % no hook predicates defined or defined but with no clauses for this particular coinductive predicate head
Hook = (HeadStack = BodyStack)
).
% reports missing predicate directives
'$lgt_report_missing_directives'(_, _) :-
'$lgt_compiler_flag'(missing_directives, silent),
!.
% reports missing scope directives for dynamic predicates
'$lgt_report_missing_directives'(category, Entity) :-
'$lgt_pp_dynamic_'(Head, Original, File, Lines),
% declared dynamic predicate or non-terminal in a category are for objects
functor(Head, Functor, Arity),
\+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _),
% but missing corresponding scope directive
\+ '$lgt_pp_implemented_protocol_'(_, _, _, _, _),
\+ '$lgt_pp_extended_category_'(_, _, _, _, _, _),
% nowhere from inheriting a predicate scope declaration
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_scope_directive(File, Lines, category, Entity, (dynamic)/1, Original)
),
fail.
% reports missing scope directives for multifile predicates
'$lgt_report_missing_directives'(Type, Entity) :-
'$lgt_pp_multifile_'(Head, Original, File, Lines),
% declared multifile predicate
functor(Head, Functor, Arity),
\+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _),
% but missing corresponding scope directive
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_scope_directive(File, Lines, Type, Entity, (multifile)/1, Original)
),
fail.
% reports missing meta_predicate/1 directives for meta-predicates
'$lgt_report_missing_directives'(Type, Entity) :-
'$lgt_pp_missing_meta_predicate_directive_'(Head, File, Lines),
functor(Head, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_defines_non_terminal_'(Functor, NonTerminalArity, Arity) ->
'$lgt_print_message'(
warning(missing_directives),
missing_predicate_directive(File, Lines, Type, Entity, (meta_non_terminal)/1, Functor//NonTerminalArity)
)
; '$lgt_print_message'(
warning(missing_directives),
missing_predicate_directive(File, Lines, Type, Entity, (meta_predicate)/1, Functor/Arity)
)
),
fail.
% reports missing multifile/1 directives
'$lgt_report_missing_directives'(Type, Entity) :-
'$lgt_pp_missing_multifile_directive_'(PI, File, Lines),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_predicate_directive(File, Lines, Type, Entity, (multifile)/1, PI)
),
fail.
% reports missing dynamic/1 directives
'$lgt_report_missing_directives'(Type, Entity) :-
'$lgt_pp_missing_dynamic_directive_'(Head, File, Lines),
functor(Head, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_predicate_directive(File, Lines, Type, Entity, (dynamic)/1, Functor/Arity)
),
fail.
% reports missing discontiguous/1 directives
'$lgt_report_missing_directives'(Type, Entity) :-
'$lgt_pp_missing_discontiguous_directive_'(Head, File, Lines),
functor(Head, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_predicate_directive(File, Lines, Type, Entity, (discontiguous)/1, Functor/Arity)
),
fail.
% reports missing scope directives for mode2 and info/2 directives
'$lgt_report_missing_directives'(Type, Entity) :-
( '$lgt_pp_mode_'(Mode, _, File, Lines),
functor(Mode, Functor, Arity),
Directive = (mode)/2
; '$lgt_pp_predicate_info_'(Functor/Arity, _, File, Lines),
Directive = info/2
),
% documented predicate or non-terminal
\+ '$lgt_pp_non_terminal_'(Functor, Arity, _),
\+ '$lgt_pp_public_'(Functor, Arity, _, _),
\+ '$lgt_pp_protected_'(Functor, Arity, _, _),
\+ '$lgt_pp_private_'(Functor, Arity, _, _),
% but missing scope directive
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_scope_directive(File, Lines, Type, Entity, Directive, Functor/Arity)
),
fail.
'$lgt_report_missing_directives'(Type, Entity) :-
( Type == object ->
'$lgt_pp_referenced_object_'(Entity, File, Lines)
; Type == category ->
'$lgt_pp_referenced_category_'(Entity, File, Lines)
; % Type == protocol
fail
),
setof(Predicate, '$lgt_pp_missing_use_module_directive_'(Module, Predicate), Predicates),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(missing_directives),
missing_predicate_directive(File, Lines, Type, Entity, (:- use_module(Module,Predicates)))
),
fail.
'$lgt_report_missing_directives'(_, _).
% '$lgt_report_unknown_predicate_call'(@compilation_mode, @callable, @lines)
%
% reports unknown predicates and non-terminals
'$lgt_report_unknown_predicate_call'(runtime, _, _).
'$lgt_report_unknown_predicate_call'(compile(_,_,_), Pred, Lines) :-
'$lgt_compiler_flag'(unknown_predicates, Value),
'$lgt_report_unknown_predicate_call_aux'(Value, Pred, Lines).
'$lgt_report_unknown_predicate_call_aux'(silent, _, _).
'$lgt_report_unknown_predicate_call_aux'(error, Functor/Arity, _) :-
( '$lgt_pp_calls_non_terminal_'(Functor, Arity2, Arity, _) ->
throw(existence_error(non_terminal, Functor//Arity2))
; throw(existence_error(predicate, Functor/Arity))
).
'$lgt_report_unknown_predicate_call_aux'(warning, Functor/Arity, Lines) :-
% we may be compiling an auxiliary clause and thus unable
% to use the '$lgt_source_file_context'/4 predicate
( '$lgt_source_file_context'(File, Lines, Type, Entity) ->
true
; '$lgt_pp_file_paths_flags_'(_, _, File, _, _),
'$lgt_pp_entity_'(Type, Entity, _)
),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_calls_non_terminal_'(Functor, Arity2, Arity, _) ->
'$lgt_print_message'(
warning(unknown_predicates),
unknown_non_terminal_called_but_not_defined(File, Lines, Type, Entity, Functor//Arity2)
)
; '$lgt_print_message'(
warning(unknown_predicates),
unknown_predicate_called_but_not_defined(File, Lines, Type, Entity, Functor/Arity)
)
).
% '$lgt_report_undefined_predicate_call'(@compilation_mode, @callable, @lines)
%
% reports calls to declared, static, but undefined predicates and non-terminals
'$lgt_report_undefined_predicate_call'(runtime, _, _).
'$lgt_report_undefined_predicate_call'(compile(_,_,_), Pred, Lines) :-
'$lgt_compiler_flag'(undefined_predicates, Value),
'$lgt_report_undefined_predicate_call_aux'(Value, Pred, Lines).
'$lgt_report_undefined_predicate_call_aux'(silent, _, _).
'$lgt_report_undefined_predicate_call_aux'(error, Functor/Arity, _) :-
( '$lgt_pp_calls_non_terminal_'(Functor, Arity2, Arity, _) ->
throw(existence_error(procedure, Functor//Arity2))
; throw(existence_error(procedure, Functor/Arity))
).
'$lgt_report_undefined_predicate_call_aux'(warning, Functor/Arity, Lines) :-
% we may be compiling an auxiliary clause and thus unable
% to use the '$lgt_source_file_context'/4 predicate
( '$lgt_source_file_context'(File, Lines, Type, Entity) ->
true
; '$lgt_pp_file_paths_flags_'(_, _, File, _, _),
'$lgt_pp_entity_'(Type, Entity, _)
),
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_calls_non_terminal_'(Functor, Arity2, Arity, _) ->
'$lgt_print_message'(
warning(undefined_predicates),
declared_static_non_terminal_called_but_not_defined(File, Lines, Type, Entity, Functor//Arity2)
)
; '$lgt_print_message'(
warning(undefined_predicates),
declared_static_predicate_called_but_not_defined(File, Lines, Type, Entity, Functor/Arity)
)
).
% '$lgt_report_non_portable_calls'(@entity_type, @entity_identifier)
%
% reports non-portable predicate and function calls in the body of object and category predicates
'$lgt_report_non_portable_calls'(protocol, _) :-
!.
'$lgt_report_non_portable_calls'(_, _) :-
'$lgt_compiler_flag'(portability, silent),
!.
'$lgt_report_non_portable_calls'(Type, Entity) :-
'$lgt_pp_non_portable_predicate_'(Head, File, Lines),
functor(Head, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
non_standard_predicate_call(File, Lines, Type, Entity, Functor/Arity)
),
fail.
'$lgt_report_non_portable_calls'(Type, Entity) :-
'$lgt_pp_non_portable_function_'(Function, File, Lines),
functor(Function, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
non_standard_arithmetic_function_call(File, Lines, Type, Entity, Functor/Arity)
),
fail.
'$lgt_report_non_portable_calls'(_, _).
% '$lgt_report_missing_functions'(@entity_type, @entity_identifier)
%
% reports non-portable predicate and function calls in the body of object and category predicates
'$lgt_report_missing_functions'(protocol, _) :-
!.
'$lgt_report_missing_functions'(_, _) :-
'$lgt_compiler_flag'(portability, silent),
!.
'$lgt_report_missing_functions'(Type, Entity) :-
'$lgt_pp_missing_function_'(Function, File, Lines),
functor(Function, Functor, Arity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(portability),
missing_function(File, Lines, Type, Entity, Functor/Arity)
),
fail.
'$lgt_report_missing_functions'(_, _).
% '$lgt_report_predicates_called_as_non_terminals'(@entity_type, @entity_identifier)
%
% reports calls to predicates as non-terminals from grammar rules
'$lgt_report_predicates_called_as_non_terminals'(protocol, _) :-
!.
'$lgt_report_predicates_called_as_non_terminals'(_, _) :-
'$lgt_compiler_flag'(grammar_rules, silent),
!.
'$lgt_report_predicates_called_as_non_terminals'(Type, Entity) :-
'$lgt_pp_calls_non_terminal_'(Functor, Arity, ExtArity, Lines),
\+ '$lgt_pp_defines_non_terminal_'(Functor, Arity, ExtArity),
'$lgt_pp_defines_predicate_'(_, Functor/ExtArity, _, _, _, _),
% actually require at least one clause to be defined as the predicate may be dynamic
'$lgt_pp_number_of_clauses_rules_'(Functor, ExtArity, _, _),
'$lgt_pp_file_paths_flags_'(_, _, File, _, _),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(grammar_rules),
calls_predicate_as_non_terminal(File, Lines, Type, Entity, Functor/ExtArity)
),
fail.
'$lgt_report_predicates_called_as_non_terminals'(_, _).
% '$lgt_report_non_tail_recursive_predicates'(@entity_type, @entity_identifier)
%
% reports non-tail recursive predicate definitions
'$lgt_report_non_tail_recursive_predicates'(protocol, _) :-
!.
'$lgt_report_non_tail_recursive_predicates'(Type, Entity) :-
'$lgt_compiler_flag'(tail_recursive, warning),
'$lgt_pp_non_tail_recursive_predicate_'(Functor, Arity, File, Lines),
'$lgt_pp_predicate_recursive_calls_'(Functor, Arity, Count),
Count =:= 1,
'$lgt_increment_compiling_warnings_counter',
( '$lgt_pp_defines_non_terminal_'(Functor, Arity2, Arity) ->
'$lgt_print_message'(
warning(tail_recursive),
non_tail_recursive_non_terminal(File, Lines, Type, Entity, Functor//Arity2)
)
; '$lgt_print_message'(
warning(tail_recursive),
non_tail_recursive_predicate(File, Lines, Type, Entity, Functor/Arity)
)
),
fail.
'$lgt_report_non_tail_recursive_predicates'(_, _).
% '$lgt_write_encoding_directive'(@stream, +atom)
%
% writes the encoding/1 directive (if supported in generated code);
% it must be the first term in the file
'$lgt_write_encoding_directive'(Stream, Path) :-
( '$lgt_prolog_feature'(encoding_directive, full),
'$lgt_pp_file_encoding_'(Path, _, Encoding, _) ->
'$lgt_write_compiled_term'(Stream, (:- encoding(Encoding)), runtime, Path, 1)
; true
).
% '$lgt_write_entity_directives'(@stream, +atom)
%
% writes the compiled entity directives
'$lgt_write_entity_directives'(Stream, Path) :-
'$lgt_pp_directive_'(Directive),
'$lgt_write_compiled_term'(Stream, (:- Directive), runtime, Path, 1),
fail.
'$lgt_write_entity_directives'(_, _).
% '$lgt_write_prolog_terms'(@stream, atom)
%
% writes any Prolog clauses that appear before an entity opening directive
'$lgt_write_prolog_terms'(Stream, Path) :-
'$lgt_pp_prolog_term_'(Term, Line-_),
'$lgt_write_compiled_term'(Stream, Term, user, Path, Line),
fail.
'$lgt_write_prolog_terms'(_, _).
% '$lgt_write_entity_clauses'(@stream, +atom, +atom)
%
% writes Logtalk entity clauses
'$lgt_write_entity_clauses'(Stream, Path, _) :-
'$lgt_pp_dcl_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail.
'$lgt_write_entity_clauses'(Stream, Path, _) :-
'$lgt_pp_def_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail.
'$lgt_write_entity_clauses'(Stream, Path, _) :-
'$lgt_pp_ddef_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail.
'$lgt_write_entity_clauses'(Stream, Path, _) :-
'$lgt_pp_super_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail.
'$lgt_write_entity_clauses'(Stream, Path, Rnm) :-
'$lgt_pp_predicate_alias_'(Entity, Pred, Alias, _, _, _),
Clause =.. [Rnm, Entity, Pred, Alias],
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail.
'$lgt_write_entity_clauses'(Stream, Path, Rnm) :-
Catchall =.. [Rnm, _, Pred, Pred],
'$lgt_write_compiled_term'(Stream, Catchall, runtime, Path, 1),
fail.
'$lgt_write_entity_clauses'(Stream, Path, _) :-
'$lgt_pp_final_entity_term_'(Clause, Line-_),
'$lgt_write_compiled_term'(Stream, Clause, user, Path, Line),
fail.
'$lgt_write_entity_clauses'(Stream, Path, _) :-
'$lgt_pp_final_entity_aux_clause_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, aux, Path, 1),
fail.
'$lgt_write_entity_clauses'(_, _, _).
% '$lgt_write_runtime_clauses'(@stream, +atom)
%
% writes the entity runtime multifile and dynamic directives and the entity
% runtime clauses for all defined entities
'$lgt_write_runtime_clauses'(Stream, Path) :-
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_current_protocol_'/5),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_current_category_'/6),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_current_object_'/11),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_entity_property_'/2),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_predicate_property_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_implements_protocol_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_imports_category_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_instantiates_class_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_specializes_class_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_extends_category_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_extends_object_'/3),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_extends_protocol_'/3),
'$lgt_write_runtime_static_clauses'(Stream, Path, '$lgt_uses_predicate_'/5),
'$lgt_write_runtime_static_clauses'(Stream, Path, '$lgt_use_module_predicate_'/5),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_loaded_file_'/7),
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, '$lgt_included_file_'/4).
'$lgt_write_runtime_dynamic_clauses'(Stream, Path, Functor/Arity) :-
functor(Clause, Functor, Arity),
( \+ '$lgt_pp_runtime_clause_'(Clause) ->
true
; '$lgt_write_compiled_term'(Stream, (:- multifile(Functor/Arity)), runtime, Path, 1),
'$lgt_write_compiled_term'(Stream, (:- dynamic(Functor/Arity)), runtime, Path, 1),
( '$lgt_pp_runtime_clause_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail
; true
)
).
'$lgt_write_runtime_static_clauses'(Stream, Path, Functor/Arity) :-
functor(Clause, Functor, Arity),
( \+ '$lgt_pp_runtime_clause_'(Clause) ->
true
; '$lgt_write_compiled_term'(Stream, (:- multifile(Functor/Arity)), runtime, Path, 1),
( '$lgt_pp_runtime_clause_'(Clause),
'$lgt_write_compiled_term'(Stream, Clause, runtime, Path, 1),
fail
; true
)
).
% '$lgt_write_initialization_directive'(@stream, +atom)
%
% writes the initialization directive for the compiled source file,
% a conjunction of the initialization goals of the defined entities
'$lgt_write_initialization_directive'(Stream, Path) :-
'$lgt_initialization_goal'(Goal),
( Goal == true ->
true
; '$lgt_write_compiled_term'(Stream, (:- initialization(Goal)), runtime, Path, 1)
).
% '$lgt_initialization_goal'(-callable)
%
% source file initialization goal constructed from object initialization
% directives and from source file initialization/1 directives if present
'$lgt_initialization_goal'(InitializationGoal) :-
findall(
Line-Goal,
( '$lgt_pp_file_entity_initialization_'(_, Goal, Line-_)
; '$lgt_pp_file_initialization_'(Goal, Line-_)
),
LineGoals
),
% ensure source file textual order for the initialization goals
% (this assumes that the backend Prolog system provides access to
% read term position...)
keysort(LineGoals, SortedLineGoals),
findall(
Goal,
'$lgt_member'(_-Goal, SortedLineGoals),
Goals
),
'$lgt_list_to_conjunction'(Goals, InitializationGoal).
% converts a list of goals into a conjunction of goals
'$lgt_list_to_conjunction'([], true).
'$lgt_list_to_conjunction'([Goal| Goals], Conjunction) :-
'$lgt_list_to_conjunction'(Goals, Goal, Conjunction).
'$lgt_list_to_conjunction'([], Conjunction, Conjunction).
'$lgt_list_to_conjunction'([Next| Goals], Goal, (Goal,Conjunction)) :-
'$lgt_list_to_conjunction'(Goals, Next, Conjunction).
% converts a conjunction into a list of terms
'$lgt_conjunction_to_list'(Term, [Term]) :-
var(Term),
!.
'$lgt_conjunction_to_list'((Term, Conjunction), [Term| Terms]) :-
!,
'$lgt_conjunction_to_list'(Conjunction, Terms).
'$lgt_conjunction_to_list'(Term, [Term]).
% generates and asserts the initialization goal for the object being compiled
'$lgt_generate_file_object_initialization_goal' :-
'$lgt_pp_entity_'(_, Object, Prefix),
( '$lgt_prolog_feature'(threads, supported),
setof(Mutex, Head^File^Lines^'$lgt_pp_synchronized_'(Head, Mutex, File, Lines), Mutexes) ->
Goal1 = '$lgt_create_mutexes'(Mutexes)
; Goal1 = true
),
( '$lgt_pp_threaded_' ->
Goal2 = '$lgt_init_object_message_queue'(Prefix)
; Goal2 = true
),
% an object may contain multiple initialization/1 directives
( bagof(ObjectInitGoal, Lines^'$lgt_pp_final_object_initialization_'(ObjectInitGoal, Lines), ObjectInitGoals) ->
'$lgt_list_to_conjunction'(ObjectInitGoals, Goal3),
'$lgt_remove_redundant_calls'((Goal1, Goal2, Goal3), Goal)
; '$lgt_remove_redundant_calls'((Goal1, Goal2), Goal)
),
( Goal == true ->
true
; '$lgt_pp_referenced_object_'(Object, _File, Lines),
assertz('$lgt_pp_file_entity_initialization_'(Object, Goal, Lines))
).
% generates and asserts the initialization goal for the category being compiled
'$lgt_generate_file_category_initialization_goal' :-
( '$lgt_prolog_feature'(threads, supported),
setof(Mutex, Head^File^Lines^'$lgt_pp_synchronized_'(Head, Mutex, File, Lines), Mutexes) ->
'$lgt_pp_referenced_category_'(Category, _File, Lines),
assertz('$lgt_pp_file_entity_initialization_'(Category, '$lgt_create_mutexes'(Mutexes), Lines))
; true
).
% '$lgt_assert_dynamic_entity'(+atom)
%
% adds a dynamically created entity to memory
'$lgt_assert_dynamic_entity'(object) :-
'$lgt_pp_object_'(_, _, _, _, _, _, _, _, _, Rnm, _),
'$lgt_assert_dynamic_entity'(object, Rnm),
'$lgt_call_initialization_goal'.
'$lgt_assert_dynamic_entity'(protocol) :-
'$lgt_pp_protocol_'(_, _, _, Rnm, _),
'$lgt_assert_dynamic_entity'(protocol, Rnm),
'$lgt_call_initialization_goal'.
'$lgt_assert_dynamic_entity'(category) :-
'$lgt_pp_category_'(_, _, _, _, Rnm, _),
'$lgt_assert_dynamic_entity'(category, Rnm),
'$lgt_call_initialization_goal'.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_directive_'(dynamic(Functor/Arity)),
functor(Pred, Functor, Arity),
asserta(Pred),
retract(Pred),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_dcl_'(Clause),
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_def_'(Clause),
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_ddef_'(Clause),
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_super_'(Clause),
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(_, Rnm) :-
'$lgt_pp_predicate_alias_'(Entity, Pred, Alias, _, _, _),
Clause =.. [Rnm, Entity, Pred, Alias],
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(_, Rnm) :-
Catchall =.. [Rnm, _, Pred, Pred],
'$lgt_assertz_entity_clause'(Catchall, aux),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_final_entity_term_'(Clause, _),
'$lgt_assertz_entity_clause'(Clause, user),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_final_entity_aux_clause_'(Clause),
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(Type, _) :-
'$lgt_save_entity_runtime_clause'(Type),
fail.
'$lgt_assert_dynamic_entity'(_, _) :-
'$lgt_pp_runtime_clause_'(Clause),
'$lgt_assertz_entity_clause'(Clause, aux),
fail.
'$lgt_assert_dynamic_entity'(_, _).
% '$lgt_call_initialization_goal'
%
% calls any defined initialization goals for a dynamically created entity
'$lgt_call_initialization_goal' :-
( '$lgt_prolog_feature'(threads, supported),
setof(Mutex, Head^File^Lines^'$lgt_pp_synchronized_'(Head, Mutex, File, Lines), Mutexes) ->
'$lgt_create_mutexes'(Mutexes)
; true
),
( '$lgt_pp_object_'(_, Prefix, _, _, _, _, _, _, _, _, _),
'$lgt_pp_threaded_' ->
'$lgt_init_object_message_queue'(Prefix)
; true
),
% an object may contain multiple initialization/1 directives
( bagof(Goal, Lines^'$lgt_pp_final_object_initialization_'(Goal, Lines), GoalList) ->
'$lgt_list_to_conjunction'(GoalList, Goals),
once(Goals)
; true
),
% complementing categories add a file initialization goal
( '$lgt_pp_file_initialization_'(InitializationGoal, _) ->
once(InitializationGoal)
; true
).
% '$lgt_construct_prototype_functors'(+object_identifier, -atom, -atom, -atom, -atom, -atom, -atom, -atom, -atom, -atom)
%
% constructs functors used in the compiled code of an object playing the role of a prototype
'$lgt_construct_prototype_functors'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm) :-
( '$lgt_current_object_'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, Flags),
Flags /\ 1 =:= 1 ->
% loaded, built-in object
true
; '$lgt_construct_entity_prefix'(Obj, Prefix),
atom_concat(Prefix, '_dcl', Dcl),
atom_concat(Prefix, '_def', Def),
atom_concat(Prefix, '_super', Super),
IDcl = Dcl,
IDef = Def,
atom_concat(Prefix, '_ddcl', DDcl),
atom_concat(Prefix, '_ddef', DDef),
atom_concat(Prefix, '_alias', Rnm)
).
% '$lgt_construct_ic_functors'(+object_identifier, -atom, -atom, -atom, -atom, -atom, -atom, -atom, -atom, -atom)
%
% constructs functors used in the compiled code of an object playing the role of a class or an instance
'$lgt_construct_ic_functors'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm) :-
( '$lgt_current_object_'(Obj, Prefix, Dcl, Def, Super, IDcl, IDef, DDcl, DDef, Rnm, Flags),
Flags /\ 1 =:= 1 ->
% loaded, built-in object
true
; '$lgt_construct_entity_prefix'(Obj, Prefix),
atom_concat(Prefix, '_dcl', Dcl),
atom_concat(Prefix, '_def', Def),
atom_concat(Prefix, '_super', Super),
atom_concat(Prefix, '_idcl', IDcl),
atom_concat(Prefix, '_idef', IDef),
atom_concat(Prefix, '_ddcl', DDcl),
atom_concat(Prefix, '_ddef', DDef),
atom_concat(Prefix, '_alias', Rnm)
).
% '$lgt_construct_protocol_functors'(+protocol_identifier, -atom, -atom, -atom)
%
% constructs functors used in the compiled code of a protocol
'$lgt_construct_protocol_functors'(Ptc, Prefix, Dcl, Rnm) :-
( '$lgt_current_protocol_'(Ptc, Prefix, Dcl, Rnm, Flags),
Flags /\ 1 =:= 1 ->
% loaded, built-in protocol
true
; '$lgt_construct_entity_prefix'(Ptc, Prefix),
atom_concat(Prefix, '_dcl', Dcl),
atom_concat(Prefix, '_alias', Rnm)
).
% '$lgt_construct_category_functors'(+category_identifier, -atom, -atom, -atom, -atom)
%
% constructs functors used in the compiled code of a category
'$lgt_construct_category_functors'(Ctg, Prefix, Dcl, Def, Rnm) :-
( '$lgt_current_category_'(Ctg, Prefix, Dcl, Def, Rnm, Flags),
Flags /\ 1 =:= 1 ->
% loaded, built-in category
true
; '$lgt_construct_entity_prefix'(Ctg, Prefix),
atom_concat(Prefix, '_dcl', Dcl),
atom_concat(Prefix, '_def', Def),
atom_concat(Prefix, '_alias', Rnm)
).
% '$lgt_entity_to_prefix'(@entity_identifier, -atom)
%
% converts an entity identifier into an entity prefix (used in the compiled code)
% note that objects, categories, and protocols share the same namespace
'$lgt_entity_to_prefix'(Entity, Prefix) :-
( '$lgt_current_object_'(Entity, Prefix, _, _, _, _, _, _, _, _, _) ->
true
; '$lgt_current_protocol_'(Entity, Prefix, _, _, _) ->
true
; '$lgt_current_category_'(Entity, Prefix, _, _, _, _) ->
true
; '$lgt_construct_entity_prefix'(Entity, Prefix)
).
% '$lgt_prefix_to_entity'(+atom, -entity_identifier)
%
% reverses the entity prefix used in the compiled code
% note that objects, categories, and protocols share the same namespace
'$lgt_prefix_to_entity'(Prefix, Entity) :-
( '$lgt_current_object_'(Entity, Prefix, _, _, _, _, _, _, _, _, _) ->
true
; '$lgt_current_protocol_'(Entity, Prefix, _, _, _) ->
true
; '$lgt_current_category_'(Entity, Prefix, _, _, _, _) ->
true
; '$lgt_deconstruct_entity_prefix'(Prefix, Entity) ->
true
; throw(representation_error(entity_prefix))
).
% '$lgt_construct_entity_prefix'(@entity_identifier, -atom)
%
% constructs the entity prefix used in the compiled code from the entity identifier
%
% prefix = code prefix + entity functor + "#" + entity arity + "."
'$lgt_construct_entity_prefix'(Entity, Prefix) :-
'$lgt_compiler_flag'(code_prefix, CodePrefix),
% the functor code prefix can be used to hide internal predicates (by
% defining it as '$' when using most backend Prolog compilers) and to
% avoid conflicts with other predicates
functor(Entity, Functor, Arity),
atom_concat(CodePrefix, Functor, Prefix0),
( '$lgt_arity_#atom.'(Arity, ArityAtom) ->
true
; number_codes(Arity, ArityCodes),
atom_codes(ArityAtom0, ArityCodes),
atom_concat('#', ArityAtom0, ArityAtom1),
atom_concat(ArityAtom1, '.', ArityAtom)
),
atom_concat(Prefix0, ArityAtom, Prefix).
% avoid costly atom computations for the most common cases
'$lgt_arity_#atom.'(0, '#0.').
'$lgt_arity_#atom.'(1, '#1.').
'$lgt_arity_#atom.'(2, '#2.').
'$lgt_arity_#atom.'(3, '#3.').
'$lgt_arity_#atom.'(4, '#4.').
'$lgt_arity_#atom.'(5, '#5.').
'$lgt_arity_#atom.'(6, '#6.').
'$lgt_arity_#atom.'(7, '#7.').
'$lgt_arity_#atom.'(8, '#8.').
'$lgt_arity_#atom.'(9, '#9.').
% '$lgt_deconstruct_entity_prefix'(+atom, -entity_identifier)
%
% deconstructs the entity prefix used in the compiled code
% returning the corresponding entity identifier template
'$lgt_deconstruct_entity_prefix'(Prefix, Entity) :-
% valid values of the code_prefix flag are single character atoms
sub_atom(Prefix, 1, _, 0, Entity0),
atom_concat(Entity1, '.', Entity0),
% locate the rightmost #
sub_atom(Entity1, Before, 1, After, '#'),
Lines is Before + 1,
sub_atom(Entity1, Lines, _, 0, Rest),
\+ sub_atom(Rest, _, 1, _, '#'), !,
sub_atom(Entity1, 0, Before, _, Functor),
sub_atom(Entity1, _, After, 0, ArityAtom),
atom_codes(ArityAtom, ArityCodes),
number_codes(Arity, ArityCodes),
functor(Entity, Functor, Arity).
% '$lgt_compile_aux_clauses'(@list(clause))
%
% compiles a list of auxiliary predicate clauses;
% used mainly in conjunction with term_expansion/2 and goal_expansion/2 hook predicates
'$lgt_compile_aux_clauses'([Clause| Clauses]) :-
% avoid making a predicate discontiguous by accident by using a
% compilation mode that ensures that the auxiliary clauses will
% be written after the user clauses
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, compile(aux,_,_), _, '-'(0,0), _),
'$lgt_compile_clause'(Clause, Ctx),
'$lgt_compile_aux_clauses'(Clauses).
'$lgt_compile_aux_clauses'([]).
% '$lgt_entity_prefix'(?entity_identifier, ?atom)
%
% converts between entity identifiers and internal entity prefixes;
% used mainly in hook objects for processing proprietary directives
'$lgt_entity_prefix'(Entity, Prefix) :-
( var(Entity), var(Prefix) ->
'$lgt_pp_entity_'(_, Entity, Prefix)
; callable(Entity) ->
'$lgt_entity_to_prefix'(Entity, Prefix)
; atom(Prefix),
'$lgt_prefix_to_entity'(Prefix, Entity)
).
% '$lgt_compile_predicate_heads'(@list(callable), ?entity_identifier, -list(callable), @compilation_context)
% '$lgt_compile_predicate_heads'(@callable, ?entity_identifier, -callable, @term)
%
% compiles a single predicate head, a conjunction of predicate heads, or a list of
% predicate heads; used mainly in hook objects for processing proprietary directives
%
% the predicate heads are compiled in the context of the specified entity or in the context
% of the entity being compiled when the entity argument is not instantiated
'$lgt_compile_predicate_heads'(Heads, Entity, THeads, Ctx) :-
'$lgt_check'(var_or_entity_identifier, Entity),
'$lgt_entity_prefix'(Entity, Prefix),
'$lgt_compile_predicate_heads_aux'(Heads, Prefix, THeads, Ctx).
'$lgt_compile_predicate_heads_aux'(Heads, _, _, _) :-
var(Heads),
throw(instantiation_error).
'$lgt_compile_predicate_heads_aux'([], _, [], _) :-
!.
'$lgt_compile_predicate_heads_aux'([Head| Heads], Prefix, [THead| THeads], Ctx) :-
!,
'$lgt_compile_predicate_heads_aux'(Head, Prefix, THead, Ctx),
'$lgt_compile_predicate_heads_aux'(Heads, Prefix, THeads, Ctx).
'$lgt_compile_predicate_heads_aux'((Head, Heads), Prefix, (THead, THeads), Ctx) :-
!,
'$lgt_compile_predicate_heads_aux'(Head, Prefix, THead, Ctx),
'$lgt_compile_predicate_heads_aux'(Heads, Prefix, THeads, Ctx).
'$lgt_compile_predicate_heads_aux'(Head, Prefix, THead, Ctx) :-
'$lgt_check'(callable, Head),
functor(Head, Functor, Arity),
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity),
functor(THead, TFunctor, TArity),
'$lgt_unify_head_thead_arguments'(Head, THead, Ctx).
% '$lgt_decompile_predicate_heads'(+list(callable), ?entity_identifier, ?atom, -list(callable))
% '$lgt_decompile_predicate_heads'(+callable, ?entity_identifier, ?atom, -callable)
%
% decompiles the predicate heads used for compiled predicates;
%
% all the compiled predicate heads must refer to the same entity
% (which must be loaded) in order for this predicate to succeed
'$lgt_decompile_predicate_heads'(THeads, Entity, Type, Heads) :-
'$lgt_check'(var_or_entity_identifier, Entity),
'$lgt_decompile_predicate_heads'(THeads, Entity, Type, _, Heads).
'$lgt_decompile_predicate_heads'(THeads, _, _, _, _) :-
var(THeads),
throw(instantiation_error).
'$lgt_decompile_predicate_heads'([], _, _, _, []) :-
!.
'$lgt_decompile_predicate_heads'([THead| THeads], Entity, Type, Prefix, [Head| Heads]) :-
!,
'$lgt_decompile_predicate_heads'(THead, Entity, Type, Prefix, Head),
'$lgt_decompile_predicate_heads'(THeads, Entity, Type, Prefix, Heads).
'$lgt_decompile_predicate_heads'(':'(Module,THead), Entity, Type, Prefix, Head) :-
atom(Module),
'$lgt_user_module_qualification'(xx, ':'(Module,xx)),
!,
'$lgt_decompile_predicate_heads'(THead, Entity, Type, Prefix, Head).
'$lgt_decompile_predicate_heads'(THead, Entity, Type, Prefix, Head) :-
callable(THead),
functor(THead, TFunctor, TArity),
( var(Prefix) ->
( '$lgt_current_object_'(Entity, Prefix, _, _, _, _, _, _, _, _, _),
Type = object
; '$lgt_current_category_'(Entity, Prefix, _, _, _, _),
Type = category
; '$lgt_current_protocol_'(Entity, Prefix, _, _, _),
Type = protocol
)
; true
),
'$lgt_decompile_predicate_indicator'(Prefix, TFunctor/TArity, Functor/Arity),
functor(Head, Functor, Arity),
'$lgt_unify_head_thead_arguments'(Head, THead, _),
!.
% '$lgt_compile_predicate_indicators'(+list(predicate_indicator), ?entity_identifier, -list(predicate_indicator))
% '$lgt_compile_predicate_indicators'(+predicate_indicator, ?entity_identifier, -predicate_indicator)
%
% compiles a single predicate indicator, a conjunction of predicate indicators, or a list
% of predicate indicators; used mainly in hook objects for processing proprietary directives
%
% the predicate indicators are compiled in the context of the specified entity or in the context
% of the entity being compiled when the entity argument is not instantiated
'$lgt_compile_predicate_indicators'(PIs, Entity, TPIs) :-
'$lgt_check'(var_or_entity_identifier, Entity),
'$lgt_entity_prefix'(Entity, Prefix),
'$lgt_compile_predicate_indicators_aux'(PIs, Prefix, TPIs).
'$lgt_compile_predicate_indicators_aux'(PIs, _, _) :-
var(PIs),
throw(instantiation_error).
'$lgt_compile_predicate_indicators_aux'([], _, []) :-
!.
'$lgt_compile_predicate_indicators_aux'([PI| PIs], Prefix, [TPI| TPIs]) :-
!,
'$lgt_compile_predicate_indicators_aux'(PI, Prefix, TPI),
'$lgt_compile_predicate_indicators_aux'(PIs, Prefix, TPIs).
'$lgt_compile_predicate_indicators_aux'((PI, PIs), Prefix, (TPI, TPIs)) :-
!,
'$lgt_compile_predicate_indicators_aux'(PI, Prefix, TPI),
'$lgt_compile_predicate_indicators_aux'(PIs, Prefix, TPIs).
'$lgt_compile_predicate_indicators_aux'(PI, Prefix, TFunctor/TArity) :-
( '$lgt_valid_predicate_indicator'(PI, Functor, Arity) ->
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity)
; '$lgt_valid_non_terminal_indicator'(PI, Functor, _, ExtArity) ->
'$lgt_compile_predicate_indicator'(Prefix, Functor/ExtArity, TFunctor/TArity)
; throw(type_error(predicate_indicator, PI))
).
% '$lgt_compile_predicate_indicator'(+atom, +predicate_indicator, -predicate_indicator)
%
% compiles the user predicate indicator using the encoding entity prefix + functor + # + arity
'$lgt_compile_predicate_indicator'(Prefix, Functor/Arity, TFunctor/TArity) :-
atom_concat(Prefix, Functor, TFunctor0),
( '$lgt_arity_#atom'(Arity, ArityAtom) ->
true
; number_codes(Arity, ArityCodes),
atom_codes(ArityAtom0, ArityCodes),
atom_concat('#', ArityAtom0, ArityAtom)
),
atom_concat(TFunctor0, ArityAtom, TFunctor),
% add execution context argument
TArity is Arity + 1.
% avoid costly atom computations for the most common cases
'$lgt_arity_#atom'(0, '#0').
'$lgt_arity_#atom'(1, '#1').
'$lgt_arity_#atom'(2, '#2').
'$lgt_arity_#atom'(3, '#3').
'$lgt_arity_#atom'(4, '#4').
'$lgt_arity_#atom'(5, '#5').
'$lgt_arity_#atom'(6, '#6').
'$lgt_arity_#atom'(7, '#7').
'$lgt_arity_#atom'(8, '#8').
'$lgt_arity_#atom'(9, '#9').
% '$lgt_decompile_predicate_indicator'(+atom, +predicate_indicator, -predicate_indicator)
%
% decompiles an internal predicate indicator used for a user predicate
'$lgt_decompile_predicate_indicator'(Prefix, TFunctor/TArity, Functor/Arity) :-
atom_concat(Prefix, Predicate, TFunctor),
% locate the rightmost # by looking for occurences left-to-right and
% backtracking until the rest of the atom no longer contains a #
sub_atom(Predicate, Before, 1, _, '#'),
Parsed is Before + 1,
sub_atom(Predicate, Parsed, _, 0, Rest),
\+ sub_atom(Rest, _, 1, _, '#'),
sub_atom(Predicate, 0, Before, _, Functor),
% subtract execution context argument
Arity is TArity - 1,
Arity >= 0,
!.
% '$lgt_decompile_predicate_indicators'(+list(predicate_indicator), ?entity_identifier, ?atom, -list(predicate_indicator))
% '$lgt_decompile_predicate_indicators'(+predicate_indicator, ?entity_identifier, ?atom, -predicate_indicator)
%
% reverses the predicate indicator used for a compiled predicate or a list of compiled predicates;
%
% all the compiled predicate indicators must refer to the same entity
% (which must be loaded) in order for this predicate to succeed
'$lgt_decompile_predicate_indicators'(TPIs, Entity, Type, PIs) :-
'$lgt_check'(var_or_entity_identifier, Entity),
'$lgt_decompile_predicate_indicators'(TPIs, Entity, Type, _, PIs).
'$lgt_decompile_predicate_indicators'(TPIs, _, _, _, _) :-
var(TPIs),
throw(instantiation_error).
'$lgt_decompile_predicate_indicators'([], _, _, _, []) :-
!.
'$lgt_decompile_predicate_indicators'([TPI| TPIs], Entity, Type, Prefix, [PI| PIs]) :-
!,
'$lgt_decompile_predicate_indicators'(TPI, Entity, Type, Prefix, PI),
'$lgt_decompile_predicate_indicators'(TPIs, Entity, Type, Prefix, PIs).
'$lgt_decompile_predicate_indicators'(':'(Module,TFunctor/TArity), Entity, Type, Prefix, Functor/Arity) :-
atom(Module),
'$lgt_user_module_qualification'(xx, ':'(Module,xx)),
!,
'$lgt_decompile_predicate_indicators'(TFunctor/TArity, Entity, Type, Prefix, Functor/Arity).
'$lgt_decompile_predicate_indicators'(TFunctor/TArity, Entity, Type, Prefix, Functor/Arity) :-
( var(Prefix) ->
( '$lgt_current_object_'(Entity, Prefix, _, _, _, _, _, _, _, _, _),
Type = object
; '$lgt_current_category_'(Entity, Prefix, _, _, _, _),
Type = category
; '$lgt_current_protocol_'(Entity, Prefix, _, _, _),
Type = protocol
)
; true
),
'$lgt_decompile_predicate_indicator'(Prefix, TFunctor/TArity, Functor/Arity),
!.
% '$lgt_compile_hooks'(+callable)
%
% compiles the user-defined default compiler hooks
% (replacing any existing defined hooks)
'$lgt_compile_hooks'(HookEntity) :-
'$lgt_comp_ctx'(Ctx, _, _, user, user, user, HookEntity, _, [], [], ExCtx, runtime, [], _, _),
'$lgt_execution_context'(ExCtx, user, user, user, HookEntity, [], []),
'$lgt_current_flag_'(events, Events),
'$lgt_compile_message_to_object'(term_expansion(Term, ExpandedTerm), HookEntity, TermExpansionGoal, Events, Ctx),
'$lgt_compile_message_to_object'(goal_expansion(Term, ExpandedTerm), HookEntity, GoalExpansionGoal, Events, Ctx),
retractall('$lgt_hook_term_expansion_'(_, _)),
assertz((
'$lgt_hook_term_expansion_'(Term, ExpandedTerm) :-
catch(TermExpansionGoal, Error, '$lgt_term_expansion_error'(HookEntity, Term, Error))
)),
retractall('$lgt_hook_goal_expansion_'(_, _)),
assertz((
'$lgt_hook_goal_expansion_'(Term, ExpandedTerm) :-
catch(GoalExpansionGoal, Error, '$lgt_goal_expansion_error'(HookEntity, Term, Error))
)).
% '$lgt_built_in_predicate'(@callable)
%
% checks if the argument is either a Logtalk or a Prolog built-in predicate
'$lgt_built_in_predicate'(Pred) :-
'$lgt_logtalk_built_in_predicate'(Pred, _),
!.
'$lgt_built_in_predicate'(Pred) :-
'$lgt_predicate_property'(Pred, built_in),
!.
'$lgt_built_in_predicate'(Pred) :-
'$lgt_iso_predicate'(Pred),
% hack for missing ISO standard predicate defined in the used adapter file
!.
% '$lgt_prolog_built_in_predicate'(@callable)
%
% either host Prolog native built-ins or missing ISO built-ins
% that we have defined in the correspondent adapter file
'$lgt_prolog_built_in_predicate'(Pred) :-
'$lgt_predicate_property'(Pred, built_in),
% Logtalk built-in predicates may also have the property "built_in"
% depending on the used backend Prolog compiler
\+ '$lgt_logtalk_built_in_predicate'(Pred, _),
!.
'$lgt_prolog_built_in_predicate'(Pred) :-
% ISO Prolog built-in predicate (defined in the adapter files)
'$lgt_iso_predicate'(Pred).
% '$lgt_prolog_built_in_database_predicate'(@callable)
%
% ISO Prolog standard and proprietary database predicates
'$lgt_prolog_built_in_database_predicate'(Term) :-
'$lgt_iso_database_predicate'(Term),
% ISO Prolog standard database predicate
!.
'$lgt_prolog_built_in_database_predicate'(Term) :-
'$lgt_prolog_database_predicate'(Term),
% proprietary database predicate (declared in the adapter files)
!.
% '$lgt_prolog_deprecated_built_in_predicate'(@callable, -callable)
%
% Prolog deprecated predicate that can be replaced by a call to a
% standard predicate; callers must check that the predicate is a
% built-in predicate that is not being locally redefined
'$lgt_prolog_deprecated_built_in_predicate'(current_predicate(Name, Template), current_predicate(Name/Arity)) :-
callable(Template),
Template \= ':'(_, _),
functor(Template, Name, Arity).
'$lgt_prolog_deprecated_built_in_predicate'(fail_if(Pred), \+ Pred).
'$lgt_prolog_deprecated_built_in_predicate'(get0(Code), get_code(Code)).
'$lgt_prolog_deprecated_built_in_predicate'(get0(Stream, Code), get_code(Stream, Code)).
'$lgt_prolog_deprecated_built_in_predicate'(put(Code), put_code(Code)).
'$lgt_prolog_deprecated_built_in_predicate'(put(Stream, Code), put_code(Stream, Code)).
'$lgt_prolog_deprecated_built_in_predicate'(name(Atomic, Codes), Goal) :-
( number(Atomic) ->
Goal = number_codes(Atomic, Codes)
; atom(Atomic),
( atom_length(Atomic, 1) ->
Goal = char_code(Atomic, Code),
Codes = [Code]
; Goal = atom_codes(Atomic, Codes)
)
).
'$lgt_prolog_deprecated_built_in_predicate'(not(Pred), \+ Pred).
'$lgt_prolog_deprecated_built_in_predicate'(otherwise, true).
'$lgt_prolog_deprecated_built_in_predicate'(prolog_flag(Flag, Value), current_prolog_flag(Flag, Value)) :-
atom(Flag),
'$lgt_iso_spec_flag'(Flag).
'$lgt_prolog_deprecated_built_in_predicate'(prolog_flag(Flag, Old, New), set_prolog_flag(Flag, New)) :-
var(Old),
atom(Flag),
'$lgt_iso_spec_flag'(Flag).
'$lgt_prolog_deprecated_built_in_predicate'(on_exception(Error, Goal, Handler), catch(Goal, Error, Handler)).
'$lgt_prolog_deprecated_built_in_predicate'(raise_exception(Error), throw(Error)).
% Quintus Prolog predicates for arithmetic functions
'$lgt_prolog_deprecated_built_in_predicate'(sin(X, Y), Y is sin(X)).
'$lgt_prolog_deprecated_built_in_predicate'(cos(X, Y), Y is cos(X)).
'$lgt_prolog_deprecated_built_in_predicate'(tan(X, Y), Y is tan(X)).
'$lgt_prolog_deprecated_built_in_predicate'(log(X, Y), Y is log(X)).
'$lgt_prolog_deprecated_built_in_predicate'(pow(X, Y, Z), Z is X**Y).
'$lgt_prolog_deprecated_built_in_predicate'(ceiling(X, Y), Y is ceiling(X)).
'$lgt_prolog_deprecated_built_in_predicate'(floor(X, Y), Y is floor(X)).
'$lgt_prolog_deprecated_built_in_predicate'(round(X, Y), Y is round(X)).
'$lgt_prolog_deprecated_built_in_predicate'(sqrt(X, Y), Y is sqrt(X)).
'$lgt_prolog_deprecated_built_in_predicate'(acos(X, Y), Y is acos(X)).
'$lgt_prolog_deprecated_built_in_predicate'(asin(X, Y), Y is asin(X)).
'$lgt_prolog_deprecated_built_in_predicate'(atan(X, Y), Y is atan(X)).
'$lgt_prolog_deprecated_built_in_predicate'(atan2(X, Y, Z), Z is atan2(X, Y)).
'$lgt_prolog_deprecated_built_in_predicate'(sign(X, Y), Y is sign(X)).
% '$lgt_prolog_deprecated_built_in_predicate'(@callable)
%
% Prolog deprecated built-in predicate; callers must check that the
% predicate is a built-in predicate that is not being locally redefined
'$lgt_prolog_deprecated_built_in_predicate'(current_predicate(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(get(_)).
'$lgt_prolog_deprecated_built_in_predicate'(get(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(name(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(prolog_flag(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(prolog_flag(_, _, _)).
'$lgt_prolog_deprecated_built_in_predicate'(skip(_)).
'$lgt_prolog_deprecated_built_in_predicate'(skip(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(tab(_)).
'$lgt_prolog_deprecated_built_in_predicate'(tab(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(ttynl).
'$lgt_prolog_deprecated_built_in_predicate'(ttyflush).
'$lgt_prolog_deprecated_built_in_predicate'(ttyget0(_)).
'$lgt_prolog_deprecated_built_in_predicate'(ttyget(_)).
'$lgt_prolog_deprecated_built_in_predicate'(ttyskip(_)).
'$lgt_prolog_deprecated_built_in_predicate'(ttyput(_)).
'$lgt_prolog_deprecated_built_in_predicate'(ttytab(_)).
% DEC-10 Prolog and C-Prolog legacy predicates
'$lgt_prolog_deprecated_built_in_predicate'(simple(_)).
'$lgt_prolog_deprecated_built_in_predicate'(reconsult(_)).
'$lgt_prolog_deprecated_built_in_predicate'(display(_)).
'$lgt_prolog_deprecated_built_in_predicate'(unknown(_, _)).
'$lgt_prolog_deprecated_built_in_predicate'(fileerrors).
'$lgt_prolog_deprecated_built_in_predicate'(nofileerrors).
'$lgt_prolog_deprecated_built_in_predicate'(see(_)).
'$lgt_prolog_deprecated_built_in_predicate'(tell(_)).
'$lgt_prolog_deprecated_built_in_predicate'(append(_)).
'$lgt_prolog_deprecated_built_in_predicate'(seeing(_)).
'$lgt_prolog_deprecated_built_in_predicate'(telling(_)).
'$lgt_prolog_deprecated_built_in_predicate'(seen).
'$lgt_prolog_deprecated_built_in_predicate'(told).
% Quintus Prolog predicates for arithmetic functions
'$lgt_prolog_deprecated_built_in_predicate'(log10(_, _)).
% '$lgt_prolog_deprecated_built_in_function'(@callable, -callable)
%
% Prolog deprecated function that can be replaced by a call to a
% standard function; callers must check that the function is a
% built-in function
'$lgt_prolog_deprecated_built_in_function'(ceil(Float), ceiling(Float)).
'$lgt_prolog_deprecated_built_in_function'(integer(Float), round(Float)).
% '$lgt_prolog_deprecated_built_in_function'(@callable)
%
% Prolog deprecated built-in function; callers must check that the
% function is a built-in function
'$lgt_prolog_deprecated_built_in_function'(_) :-
fail.
% Logtalk built-in methods
%
% '$lgt_built_in_method'(@callable, ?scope, ?callable, ?integer)
'$lgt_built_in_method'(Method, Scope, Meta, Flags) :-
( '$lgt_built_in_method_spec'(Method, Scope, Meta, Flags) ->
true
; % check if call/2-N
functor(Method, call, Arity),
Arity > 1,
Scope = p,
functor(Meta, call, Arity),
Closure is Arity - 1,
arg(1, Meta, Closure),
'$lgt_built_in_method_call_n_args'(Arity, Meta),
Flags = 1
).
'$lgt_built_in_method_call_n_args'(1, _) :-
!.
'$lgt_built_in_method_call_n_args'(N, Meta) :-
arg(N, Meta, *),
N2 is N - 1,
'$lgt_built_in_method_call_n_args'(N2, Meta).
% control constructs
'$lgt_built_in_method_spec'(_::_, p, '::'(*, *), 1).
'$lgt_built_in_method_spec'(::_, p, '::'(*), 1).
'$lgt_built_in_method_spec'([_], p, [*], 1).
'$lgt_built_in_method_spec'(^^_, p, '^^'(*), 1).
'$lgt_built_in_method_spec'(_<<_, p, '<<'(*, 0), 1).
'$lgt_built_in_method_spec'(_>>_, p, '>>'(*, 0), 1).
'$lgt_built_in_method_spec'(':'(_,_), p, ':'(*, 0), 1) :-
'$lgt_prolog_feature'(modules, supported).
'$lgt_built_in_method_spec'({_}, p(p(p)), '{}'(0), 1).
'$lgt_built_in_method_spec'((_,_), p(p(p)), ','(0, 0), 1).
'$lgt_built_in_method_spec'((_;_), p(p(p)), ';'(0, 0), 1).
'$lgt_built_in_method_spec'((_->_), p(p(p)), '->'(0, 0), 1).
'$lgt_built_in_method_spec'('*->'(_,_), p(p(p)), '*->'(0, 0), 1) :-
'$lgt_prolog_built_in_predicate'('*->'(_, _)).
% reflection methods
'$lgt_built_in_method_spec'(current_op(_,_,_), p(p(p)), current_op(*, *, (::)), 1).
'$lgt_built_in_method_spec'(current_predicate(_), p(p(p)), current_predicate((::)), 1).
'$lgt_built_in_method_spec'(predicate_property(_,_), p(p(p)), predicate_property((::), *), 1).
% database methods
'$lgt_built_in_method_spec'(abolish(_), p(p(p)), abolish((::)), 1).
'$lgt_built_in_method_spec'(asserta(_), p(p(p)), asserta((::)), 1).
'$lgt_built_in_method_spec'(assertz(_), p(p(p)), assertz((::)), 1).
'$lgt_built_in_method_spec'(clause(_,_), p(p(p)), clause((::), *), 1).
'$lgt_built_in_method_spec'(retract(_), p(p(p)), retract((::)), 1).
'$lgt_built_in_method_spec'(retractall(_), p(p(p)), retractall((::)), 1).
% term expansion methods
'$lgt_built_in_method_spec'(expand_term(_,_), p(p(p)), no, 1).
'$lgt_built_in_method_spec'(expand_goal(_,_), p(p(p)), no, 1).
% DCGs methods
'$lgt_built_in_method_spec'(phrase(_,_,_), p, phrase(2, *, *), 1).
'$lgt_built_in_method_spec'(phrase(_,_), p, phrase(2, *), 1).
% meta-calls plus logic and control methods
'$lgt_built_in_method_spec'(\+ _, p, \+ 0, 1).
'$lgt_built_in_method_spec'(call(_), p, call(0), 1).
'$lgt_built_in_method_spec'(once(_), p, once(0), 1).
'$lgt_built_in_method_spec'(ignore(_), p, ignore(0), 1).
'$lgt_built_in_method_spec'(!, p(p(p)), no, 1).
'$lgt_built_in_method_spec'(true, p(p(p)), no, 1).
'$lgt_built_in_method_spec'(fail, p(p(p)), no, 1).
'$lgt_built_in_method_spec'(false, p(p(p)), no, 1).
'$lgt_built_in_method_spec'(repeat, p(p(p)), no, 1).
% exception handling methods
'$lgt_built_in_method_spec'(catch(_,_,_), p, catch(0, *, 0), 1).
'$lgt_built_in_method_spec'(throw(_), p, no, 1).
% error predicates
'$lgt_built_in_method_spec'(instantiation_error, p, no, 1).
'$lgt_built_in_method_spec'(uninstantiation_error(_), p, no, 1).
'$lgt_built_in_method_spec'(type_error(_,_), p, no, 1).
'$lgt_built_in_method_spec'(domain_error(_,_), p, no, 1).
'$lgt_built_in_method_spec'(consistency_error(_,_,_), p, no, 1).
'$lgt_built_in_method_spec'(existence_error(_,_), p, no, 1).
'$lgt_built_in_method_spec'(permission_error(_,_,_), p, no, 1).
'$lgt_built_in_method_spec'(representation_error(_), p, no, 1).
'$lgt_built_in_method_spec'(evaluation_error(_), p, no, 1).
'$lgt_built_in_method_spec'(resource_error(_), p, no, 1).
'$lgt_built_in_method_spec'(syntax_error(_), p, no, 1).
'$lgt_built_in_method_spec'(system_error, p, no, 1).
% execution context methods
'$lgt_built_in_method_spec'(context(_), p, no, 1).
'$lgt_built_in_method_spec'(parameter(_,_), p, no, 1).
'$lgt_built_in_method_spec'(self(_), p, no, 1).
'$lgt_built_in_method_spec'(sender(_), p, no, 1).
'$lgt_built_in_method_spec'(this(_), p, no, 1).
% all solutions methods
'$lgt_built_in_method_spec'(bagof(_,_,_), p, bagof(*, ^, *), 1).
'$lgt_built_in_method_spec'(findall(_,_,_), p, findall(*, 0, *), 1).
'$lgt_built_in_method_spec'(findall(_,_,_,_), p, findall(*, 0, *, *), 1).
'$lgt_built_in_method_spec'(forall(_,_), p, forall(0, 0), 1).
'$lgt_built_in_method_spec'(setof(_,_,_), p, setof(*, ^, *), 1).
% Logtalk built-in error methods
%
% '$lgt_built_in_error_method'(@callable)
'$lgt_built_in_error_method'(instantiation_error).
'$lgt_built_in_error_method'(uninstantiation_error(_)).
'$lgt_built_in_error_method'(type_error(_, _)).
'$lgt_built_in_error_method'(domain_error(_, _)).
'$lgt_built_in_error_method'(consistency_error(_, _, _)).
'$lgt_built_in_error_method'(existence_error(_, _)).
'$lgt_built_in_error_method'(permission_error(_, _, _)).
'$lgt_built_in_error_method'(representation_error(_)).
'$lgt_built_in_error_method'(evaluation_error(_)).
'$lgt_built_in_error_method'(resource_error(_)).
'$lgt_built_in_error_method'(syntax_error(_)).
'$lgt_built_in_error_method'(system_error).
% Logtalk built-in meta-predicates
%
% '$lgt_logtalk_meta_predicate'(+callable, ?callable, ?atom)
'$lgt_logtalk_meta_predicate'(Pred, Meta, predicate) :-
'$lgt_built_in_method'(Pred, _, Meta, _),
Meta \== no.
% '$lgt_reserved_predicate_protocol'(?callable, ?atom)
%
% table of reserved predicate names and the built-in protocols
% where they are declared
'$lgt_reserved_predicate_protocol'(before(_, _, _), monitoring).
'$lgt_reserved_predicate_protocol'(after(_, _, _), monitoring).
'$lgt_reserved_predicate_protocol'(term_expansion(_, _), expanding).
'$lgt_reserved_predicate_protocol'(goal_expansion(_, _), expanding).
'$lgt_reserved_predicate_protocol'(forward(_), forwarding).
%'$lgt_logtalk_directive'(@callable)
%
% valid Logtalk directives; a common subset of Prolog module directives are
% also included as modules can be compiled as objects (but the specific case
% of the use_module/1 directive is handled at the Prolog adapter file level)
'$lgt_logtalk_directive'(Directive) :-
'$lgt_logtalk_opening_directive'(Directive),
!.
'$lgt_logtalk_directive'(Directive) :-
'$lgt_logtalk_closing_directive'(Directive),
!.
'$lgt_logtalk_directive'(Directive) :-
'$lgt_logtalk_entity_directive'(Directive),
!.
'$lgt_logtalk_directive'(Directive) :-
'$lgt_logtalk_predicate_directive'(Directive),
!.
% objects
'$lgt_logtalk_opening_directive'(object(_)).
'$lgt_logtalk_opening_directive'(object(_, _)).
'$lgt_logtalk_opening_directive'(object(_, _, _)).
'$lgt_logtalk_opening_directive'(object(_, _, _, _)).
'$lgt_logtalk_opening_directive'(object(_, _, _, _, _)).
% categories
'$lgt_logtalk_opening_directive'(category(_)).
'$lgt_logtalk_opening_directive'(category(_, _)).
'$lgt_logtalk_opening_directive'(category(_, _, _)).
'$lgt_logtalk_opening_directive'(category(_, _, _, _)).
% protocols
'$lgt_logtalk_opening_directive'(protocol(_)).
'$lgt_logtalk_opening_directive'(protocol(_, _)).
% Prolog module directives
'$lgt_logtalk_opening_directive'(module(_)).
'$lgt_logtalk_opening_directive'(module(_, _)).
% module/3 directives are currently not supported but must
% be recognized as entity opening directives
'$lgt_logtalk_opening_directive'(module(_, _, _)).
'$lgt_logtalk_closing_directive'(end_object).
'$lgt_logtalk_closing_directive'(end_category).
'$lgt_logtalk_closing_directive'(end_protocol).
'$lgt_logtalk_entity_directive'(built_in).
'$lgt_logtalk_entity_directive'(include(_)).
'$lgt_logtalk_entity_directive'(initialization(_)).
'$lgt_logtalk_entity_directive'((dynamic)).
'$lgt_logtalk_entity_directive'(op(_, _, _)).
'$lgt_logtalk_entity_directive'(info(_)).
'$lgt_logtalk_entity_directive'(threaded).
'$lgt_logtalk_entity_directive'(set_logtalk_flag(_, _)).
'$lgt_logtalk_entity_directive'(uses(_)).
'$lgt_logtalk_entity_directive'(use_module(_)).
'$lgt_logtalk_predicate_directive'(synchronized(_)).
'$lgt_logtalk_predicate_directive'(dynamic(_)).
'$lgt_logtalk_predicate_directive'(meta_predicate(_)).
'$lgt_logtalk_predicate_directive'(meta_non_terminal(_)).
'$lgt_logtalk_predicate_directive'(discontiguous(_)).
'$lgt_logtalk_predicate_directive'(public(_)).
'$lgt_logtalk_predicate_directive'(protected(_)).
'$lgt_logtalk_predicate_directive'(private(_)).
'$lgt_logtalk_predicate_directive'(mode(_, _)).
'$lgt_logtalk_predicate_directive'(info(_, _)).
'$lgt_logtalk_predicate_directive'(alias(_, _)).
'$lgt_logtalk_predicate_directive'(multifile(_)).
'$lgt_logtalk_predicate_directive'(coinductive(_)).
'$lgt_logtalk_predicate_directive'(uses(_, _)).
'$lgt_logtalk_predicate_directive'(use_module(_, _)).
% Prolog module directives that are recognized when compiling modules as objects
'$lgt_logtalk_predicate_directive'(export(_)).
'$lgt_logtalk_predicate_directive'(reexport(_, _)).
'$lgt_conditional_compilation_directive'(if(_)).
'$lgt_conditional_compilation_directive'(elif(_)).
'$lgt_conditional_compilation_directive'(else).
'$lgt_conditional_compilation_directive'(endif).
'$lgt_is_conditional_compilation_directive'((:- Directive)) :-
nonvar(Directive),
'$lgt_conditional_compilation_directive'(Directive).
% '$lgt_file_directive'(@callable)
%
% standard file-level directives (used for portability checking)
'$lgt_file_directive'(discontiguous(_)).
'$lgt_file_directive'(dynamic(_)).
'$lgt_file_directive'(multifile(_)).
'$lgt_file_directive'(encoding(_)).
'$lgt_file_directive'(include(_)).
'$lgt_file_directive'(use_module(_)).
'$lgt_file_directive'(use_module(_, _)).
'$lgt_file_directive'(ensure_loaded(_)).
'$lgt_file_directive'(set_prolog_flag(_, _)).
'$lgt_file_directive'(set_logtalk_flag(_, _)).
'$lgt_file_directive'(initialization(_)).
'$lgt_file_directive'(op(_, _, _)).
% utility predicates used during compilation of Logtalk entities to store and
% access compilation context information (represented by a compound term)
'$lgt_comp_ctx'(ctx(_, _, _, _, _, _, _, _, _, _, _, _, _, _)).
'$lgt_comp_ctx'(
ctx(Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, Mode, Stack, Lines, Term),
Head, HeadExCtx, Entity, Sender, This, Self, Prefix, MetaVars, MetaCallCtx, ExCtx, Mode, Stack, Lines, Term
).
% head of the clause being compiled
'$lgt_comp_ctx_head'(ctx(Head, _, _, _, _, _, _, _, _, _, _, _, _, _), Head).
% head execution context of the clause being compiled
'$lgt_comp_ctx_head_exec_ctx'(ctx(_, HeadExCtx, _, _, _, _, _, _, _, _, _, _, _, _), HeadExCtx).
% entity containing the clause being compiled (either a category or an object)
'$lgt_comp_ctx_entity'(ctx(_, _, Entity, _, _, _, _, _, _, _, _, _, _, _), Entity).
'$lgt_comp_ctx_sender'(ctx(_, _, _, Sender, _, _, _, _, _, _, _, _, _, _), Sender).
'$lgt_comp_ctx_this'(ctx(_, _, _, _, This, _, _, _, _, _, _, _, _, _), This).
'$lgt_comp_ctx_self'(ctx(_, _, _, _, _, Self, _, _, _, _, _, _, _, _), Self).
% entity prefix used to avoid predicate name conflicts
'$lgt_comp_ctx_prefix'(ctx(_, _, _, _, _, _, Prefix, _, _, _, _, _, _, _), Prefix).
'$lgt_comp_ctx_meta_vars'(ctx(_, _, _, _, _, _, _, MetaVars, _, _, _, _, _, _), MetaVars).
'$lgt_comp_ctx_meta_call_ctx'(ctx(_, _, _, _, _, _, _, _, MetaCallCtx, _, _, _, _, _), MetaCallCtx).
'$lgt_comp_ctx_exec_ctx'(ctx(_, _, _, _, _, _, _, _, _, ExCtx, _, _, _, _), ExCtx).
% compilation mode; possible values are "compile(user,_,_)", "compile(aux,_,_)", and "runtime"
'$lgt_comp_ctx_mode'(ctx(_, _, _, _, _, _, _, _, _, _, Mode, _, _, _), Mode).
% stack of coinductive hypothesis (ancestor goals)
'$lgt_comp_ctx_stack'(ctx(_, _, _, _, _, _, _, _, _, _, _, Stack, _, _), Stack).
% begin line and end line (a pair of integers) of the term being compiled
'$lgt_comp_ctx_lines'(ctx(_, _, _, _, _, _, _, _, _, _, _, _, Lines, _), Lines).
% term being compiled
'$lgt_comp_ctx_term'(ctx(_, _, _, _, _, _, _, _, _, _, _, _, _, Term), Term).
% utility predicates used to access execution context terms
'$lgt_execution_context'(c(This, Entity, r(Sender, Self, MetaCallContext, Stack)), Entity, Sender, This, Self, MetaCallContext, Stack).
% inheritance only requires updating "this" and "entity"
'$lgt_execution_context_update_this_entity'(c(OldThis, OldEntity, Rest), OldThis, OldEntity, c(NewThis, NewEntity, Rest), NewThis, NewEntity).
'$lgt_execution_context_this_entity'(c(This, Entity, _), This, Entity).
% '$lgt_term_template'(@callable, -callable)
%
% constructs a template for a callable term
'$lgt_term_template'(Term, Template) :-
functor(Term, Functor, Arity),
functor(Template, Functor, Arity).
% '$lgt_flatten_to_list'(+term, -list)
%
% flattens an item, a list of items, or a conjunction of items into a list
'$lgt_flatten_to_list'([A| B], [A| B]) :-
!.
'$lgt_flatten_to_list'([], []) :-
!.
'$lgt_flatten_to_list'((A, B), [A| BB]) :-
!,
'$lgt_flatten_to_list'(B, BB).
'$lgt_flatten_to_list'(A, [A]).
% '$lgt_valid_scope'(@nonvar).
%
% valid (user-level) scope
'$lgt_valid_scope'((private)).
'$lgt_valid_scope'(protected).
'$lgt_valid_scope'((public)).
% '$lgt_valid_predicate_indicator'(@term, -atom, -integer)
%
% valid predicate indicator
'$lgt_valid_predicate_indicator'(Functor/Arity, Functor, Arity) :-
atom(Functor),
integer(Arity),
Arity >= 0.
% '$lgt_valid_non_terminal_indicator'(@term, -atom, -integer, -integer)
%
% valid grammar rule non-terminal indicator; the last argument is the
% arity of the corresponding predicate
'$lgt_valid_non_terminal_indicator'(Functor//Arity, Functor, Arity, ExtArity) :-
atom(Functor),
integer(Arity),
Arity >= 0,
ExtArity is Arity + 2.
% '$lgt_valid_predicate_or_non_terminal_indicator'(@term, -atom, -integer)
%
% valid predicate indicator or grammar rule indicator
'$lgt_valid_predicate_or_non_terminal_indicator'(Functor/Arity, Functor, Arity) :-
atom(Functor),
integer(Arity),
Arity >= 0.
'$lgt_valid_predicate_or_non_terminal_indicator'(Functor//Arity, Functor, Arity) :-
atom(Functor),
integer(Arity),
Arity >= 0.
% '$lgt_valid_info_key_value_pair'(@term, -atom, -integer)
%
% valid info/1-2 key-value pair
'$lgt_valid_info_key_value_pair'(Key is Value, Key, Value) :-
atom(Key),
nonvar(Value).
% '$lgt_check_entity_reference'(+atom, @term, -atom, -entity_identifier)
'$lgt_check_entity_reference'(object, Ref, Scope, Object) :-
( Ref = Scope::Object ->
'$lgt_check'(scope, Scope),
'$lgt_check'(object_identifier, Object)
; Ref = Object,
Scope = (public),
'$lgt_check'(object_identifier, Object)
).
'$lgt_check_entity_reference'(protocol, Ref, Scope, Protocol) :-
( Ref = Scope::Protocol ->
'$lgt_check'(scope, Scope),
'$lgt_check'(protocol_identifier, Protocol)
; Ref = Protocol,
Scope = (public),
'$lgt_check'(protocol_identifier, Protocol)
).
'$lgt_check_entity_reference'(category, Ref, Scope, Category) :-
( Ref = Scope::Category ->
'$lgt_check'(scope, Scope),
'$lgt_check'(category_identifier, Category)
; Ref = Category,
Scope = (public),
'$lgt_check'(category_identifier, Category)
).
% '$lgt_check_closure'(@nonvar, @compilation_context)
%
% checks that a closure meta-argument is valid
'$lgt_check_closure'(Closure, _) :-
var(Closure),
!.
'$lgt_check_closure'(Free/Goal, Ctx) :-
!,
'$lgt_check_lambda_expression'(Free/Goal, Ctx).
'$lgt_check_closure'(Parameters>>Goal, Ctx) :-
!,
'$lgt_check_lambda_expression'(Parameters>>Goal, Ctx).
'$lgt_check_closure'({Closure}, _) :-
!,
'$lgt_check'(var_or_callable, Closure).
'$lgt_check_closure'(Object::Closure, _) :-
!,
'$lgt_check'(var_or_object_identifier, Object),
'$lgt_check'(var_or_callable, Closure).
'$lgt_check_closure'(::Closure, _) :-
!,
'$lgt_check'(var_or_callable, Closure).
'$lgt_check_closure'(^^Closure, _) :-
!,
'$lgt_check'(var_or_callable, Closure).
'$lgt_check_closure'(Object<>Goal, Ctx) :-
!,
% first, check for errors
'$lgt_check'(var_or_curly_bracketed_term, Free),
'$lgt_check'(list_or_partial_list, Parameters),
'$lgt_check'(var_or_callable, Goal),
% second, check for likely errors if compiling a source file
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
nonvar(Free),
nonvar(Parameters),
nonvar(Goal) ->
'$lgt_check_lambda_expression_parameters'(Parameters, Free/Parameters>>Goal, Ctx),
'$lgt_check_lambda_expression_unclassified_variables'(Free/Parameters>>Goal, Ctx),
'$lgt_check_lambda_expression_mixed_up_variables'(Free/Parameters>>Goal, Ctx)
; true
).
'$lgt_check_lambda_expression'(Free/Goal, Ctx) :-
'$lgt_check'(var_or_curly_bracketed_term, Free),
'$lgt_check'(var_or_callable, Goal),
% second, check for likely errors if compiling a source file
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
nonvar(Free),
nonvar(Goal) ->
'$lgt_check_lambda_expression_unclassified_variables'(Free/Goal, Ctx)
; true
).
'$lgt_check_lambda_expression'(Parameters>>Goal, Ctx) :-
% first, check for errors
'$lgt_check'(list_or_partial_list, Parameters),
'$lgt_check'(var_or_callable, Goal),
% second, check for likely errors if compiling a source file
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
nonvar(Parameters),
nonvar(Goal) ->
'$lgt_check_lambda_expression_parameters'(Parameters, Parameters>>Goal, Ctx),
'$lgt_check_lambda_expression_unclassified_variables'(Parameters>>Goal, Ctx)
; true
).
% '$lgt_check_lambda_expression_parameters'(@list, @callable, +compilation_context)
'$lgt_check_lambda_expression_parameters'(Parameters, Lambda, Ctx) :-
term_variables(Parameters, Variables),
'$lgt_comp_ctx_term'(Ctx, Clause),
'$lgt_check_lambda_expression_parameter_variables'(Variables, Lambda, Clause, Ctx).
'$lgt_check_lambda_expression_parameter_variables'([], _, _, _).
'$lgt_check_lambda_expression_parameter_variables'([Variable| Variables], Lambda, Clause, Ctx) :-
'$lgt_check_lambda_expression_parameter_variable'(Variable, Lambda, Clause, Ctx),
'$lgt_check_lambda_expression_parameter_variables'(Variables, Lambda, Clause, Ctx).
'$lgt_check_lambda_expression_parameter_variable'(Variable, Lambda, Clause, _) :-
'$lgt_count_variable_occurrences'(Lambda, Variable, InLambda),
'$lgt_count_variable_occurrences'(Clause, Variable, InClause),
( InClause > InLambda,
'$lgt_compiler_flag'(lambda_variables, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(lambda_variables),
parameter_variable_used_elsewhere(File, Lines, Type, Entity, Lambda, Variable)
)
; true
).
'$lgt_contains_variable'(Term, Variable) :-
Term == Variable.
'$lgt_contains_variable'(Term, Variable) :-
compound(Term),
functor(Term, _, Arity),
'$lgt_between'(1, Arity, N),
arg(N, Term, Argument),
'$lgt_contains_variable'(Argument, Variable).
'$lgt_count_variable_occurrences'(Term, Variable, N) :-
findall(1, '$lgt_contains_variable'(Term, Variable), L),
'$lgt_length'(L, 0, N).
% each lambda goal variable should be either a lambda free variable or a lambda parameter
'$lgt_check_lambda_expression_unclassified_variables'(Free/Goal, Ctx) :-
% take into account currying to avoid false positives
'$lgt_check_lambda_expression_goal_variables'(Goal, GoalVars, Ctx),
term_variables(Free, FreeVars),
'$lgt_var_subtract'(GoalVars, FreeVars, UnclassifiedVars0),
( UnclassifiedVars0 \== [],
'$lgt_compiler_flag'(lambda_variables, warning),
% reinstate relation between term variables and their names
'$lgt_comp_ctx_term'(Ctx, OriginalTerm),
'$lgt_pp_term_source_data_'(OriginalTerm, VariableNames, Singletons, _, _),
% ignore singleton (and anonymous) variables
'$lgt_filter_singleton_variables'(UnclassifiedVars0, VariableNames, Singletons, UnclassifiedVars),
UnclassifiedVars \== [] ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(lambda_variables),
unclassified_variables_in_lambda_expression(File, Lines, Type, Entity, UnclassifiedVars, Free/Goal)
)
; true
).
'$lgt_check_lambda_expression_unclassified_variables'(Parameters>>Goal, Ctx) :-
% take into account currying to avoid false positives
'$lgt_check_lambda_expression_goal_variables'(Goal, GoalVars, Ctx),
term_variables(Parameters, ParameterVars),
'$lgt_var_subtract'(GoalVars, ParameterVars, UnclassifiedVars),
( UnclassifiedVars \== [],
'$lgt_compiler_flag'(lambda_variables, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(lambda_variables),
unclassified_variables_in_lambda_expression(File, Lines, Type, Entity, UnclassifiedVars, Parameters>>Goal)
)
; true
).
'$lgt_filter_singleton_variables'([], _, _, []).
'$lgt_filter_singleton_variables'([UnclassifiedVar0| UnclassifiedVars0], VariableNames, Singletons, [UnclassifiedVar0| UnclassifiedVars]) :-
'$lgt_member'(_Name0=Variable0, VariableNames),
Variable0 == UnclassifiedVar0,
\+ (
'$lgt_member'(Name1=Variable1, Singletons),
Variable1 == UnclassifiedVar0,
% parameter variables may be singletons in the clause but still need to be classified
\+ '$lgt_parameter_variable_name'(Name1)
),
!,
'$lgt_filter_singleton_variables'(UnclassifiedVars0, VariableNames, Singletons, UnclassifiedVars).
'$lgt_filter_singleton_variables'([_| UnclassifiedVars0], VariableNames, Singletons, UnclassifiedVars) :-
'$lgt_filter_singleton_variables'(UnclassifiedVars0, VariableNames, Singletons, UnclassifiedVars).
'$lgt_check_lambda_expression_goal_variables'(Parameters>>Goal, UnqualifiedVars, Ctx) :-
!,
'$lgt_check_lambda_expression_goal_variables'(Goal, GoalVars, Ctx),
term_variables(Parameters, ParameterVars),
'$lgt_var_subtract'(GoalVars, ParameterVars, UnqualifiedVars).
'$lgt_check_lambda_expression_goal_variables'(Goal, UnqualifiedVars, Ctx) :-
'$lgt_check_closure'(Goal, Ctx),
term_variables(Goal, UnqualifiedVars).
% no lambda goal variable should be both a lambda free variable and a lambda parameter
'$lgt_check_lambda_expression_mixed_up_variables'(Free/Parameters>>Goal, _) :-
term_variables(Free, FreeVars),
term_variables(Parameters, ParameterVars),
'$lgt_intersection'(FreeVars, ParameterVars, MixedUpVars),
( MixedUpVars \== [],
'$lgt_compiler_flag'(lambda_variables, warning) ->
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(lambda_variables),
variables_with_dual_role_in_lambda_expression(File, Lines, Type, Entity, MixedUpVars, Free/Parameters>>Goal)
)
; true
).
% '$lgt_same_operator_class'(+atom, +atom)
%
% this utility predicate is used when defining new operators using op/3
% in order to know if there's an operator of the same class that should
% be backed up
'$lgt_same_operator_class'(fx, fx).
'$lgt_same_operator_class'(fx, fy).
'$lgt_same_operator_class'(fy, fx).
'$lgt_same_operator_class'(fy, fy).
'$lgt_same_operator_class'(xf, xf).
'$lgt_same_operator_class'(xf, yf).
'$lgt_same_operator_class'(yf, xf).
'$lgt_same_operator_class'(yf, yf).
'$lgt_same_operator_class'(xfx, xfx).
'$lgt_same_operator_class'(xfx, xfy).
'$lgt_same_operator_class'(xfx, yfx).
'$lgt_same_operator_class'(xfy, xfx).
'$lgt_same_operator_class'(xfy, xfy).
'$lgt_same_operator_class'(xfy, yfx).
'$lgt_same_operator_class'(yfx, xfx).
'$lgt_same_operator_class'(yfx, xfy).
'$lgt_same_operator_class'(yfx, yfx).
% '$lgt_valid_meta_predicate_template'(@term)
'$lgt_valid_meta_predicate_template'(Pred) :-
callable(Pred),
Pred =.. [_| Args],
'$lgt_valid_meta_predicate_template_args'(Args).
'$lgt_valid_meta_predicate_template_args'([]).
'$lgt_valid_meta_predicate_template_args'([Arg| Args]) :-
ground(Arg),
'$lgt_valid_meta_predicate_template_arg'(Arg),
'$lgt_valid_meta_predicate_template_args'(Args).
% meta-argument but not called
'$lgt_valid_meta_predicate_template_arg'((::)) :- !.
% non meta-argument
'$lgt_valid_meta_predicate_template_arg'(*) :- !.
% goal with possible existential variables qualification
'$lgt_valid_meta_predicate_template_arg'(^) :- !.
% goal or closure
'$lgt_valid_meta_predicate_template_arg'(Arg) :-
integer(Arg), Arg >= 0.
% '$lgt_valid_mode_template'(@nonvar)
'$lgt_valid_mode_template'(Pred) :-
Pred =.. [_| Args],
'$lgt_valid_mode_template_args'(Args).
'$lgt_valid_mode_template_args'([]).
'$lgt_valid_mode_template_args'([Arg| Args]) :-
( ground(Arg) ->
'$lgt_valid_mode_template_arg'(Arg)
; throw(instantiation_error)
),
'$lgt_valid_mode_template_args'(Args).
% '$lgt_valid_mode_template_arg'(@nonvar)
% unspecified argument, can be input, output, or both input and output
'$lgt_valid_mode_template_arg'((?)).
'$lgt_valid_mode_template_arg'('?'(_)).
% instantiated argument on predicate call, can be further instantiated by the predicate call
'$lgt_valid_mode_template_arg'((+)).
'$lgt_valid_mode_template_arg'('+'(_)).
% non-instantiated argument (i.e. a variable) on predicate call
'$lgt_valid_mode_template_arg'((-)).
'$lgt_valid_mode_template_arg'('-'(_)).
% not modified argument (i.e. not further instantiated) by the predicate call
'$lgt_valid_mode_template_arg'((@)).
'$lgt_valid_mode_template_arg'('@'(_)).
% ground argument
'$lgt_valid_mode_template_arg'((++)).
'$lgt_valid_mode_template_arg'('++'(_)).
% unbound argument
'$lgt_valid_mode_template_arg'((--)).
'$lgt_valid_mode_template_arg'('--'(_)).
% '$lgt_valid_number_of_proofs'(@nonvar)
% calling the predicate using the specified mode always fails
'$lgt_valid_number_of_proofs'(zero).
% calling the predicate using the specified mode always succeeds once
'$lgt_valid_number_of_proofs'(one).
% calling the predicate using the specified mode may succeed once or fail
'$lgt_valid_number_of_proofs'(zero_or_one).
% calling the predicate using the specified mode may fail or succeed multiple times
'$lgt_valid_number_of_proofs'(zero_or_more).
% calling the predicate using the specified mode always succeed at least once
'$lgt_valid_number_of_proofs'(one_or_more).
% calling the predicate using the specified mode either succeeds once or throws an error
'$lgt_valid_number_of_proofs'(zero_or_error).
% calling the predicate using the specified mode either fails or throws an error
'$lgt_valid_number_of_proofs'(one_or_error).
% calling the predicate using the specified mode either succeeds once or fails or throws an error
'$lgt_valid_number_of_proofs'(zero_or_one_or_error).
% calling the predicate using the specified mode may fail or succeed multiple times or throw an error
'$lgt_valid_number_of_proofs'(zero_or_more_or_error).
% calling the predicate using the specified mode may succeed one or more times or throw an error
'$lgt_valid_number_of_proofs'(one_or_more_or_error).
% calling the predicate using the specified mode throws an error
'$lgt_valid_number_of_proofs'(error).
% '$lgt_valid_predicate_property'(@nonvar)
% predicate scope (public, protected, or private)
'$lgt_valid_predicate_property'(scope(_)).
% public predicate
'$lgt_valid_predicate_property'((public)).
% protected predicate
'$lgt_valid_predicate_property'(protected).
% private predicate
'$lgt_valid_predicate_property'((private)).
% dynamic predicate
'$lgt_valid_predicate_property'((dynamic)).
% static predicate
'$lgt_valid_predicate_property'(static).
% predicate is defined in Logtalk source code
'$lgt_valid_predicate_property'(logtalk).
% predicate is defined in Prolog source code
'$lgt_valid_predicate_property'(prolog).
% predicate is defined in foreign source code (e.g. C)
'$lgt_valid_predicate_property'(foreign).
% entity containing the predicate scope directive
'$lgt_valid_predicate_property'(declared_in(_)).
% object or category containing the predicate definition
'$lgt_valid_predicate_property'(defined_in(_)).
% object or category containing the inherited but overridden predicate definition
'$lgt_valid_predicate_property'(redefined_from(_)).
% meta-predicate template
'$lgt_valid_predicate_property'(meta_predicate(_)).
% coinductive predicate template
'$lgt_valid_predicate_property'(coinductive(_)).
% built-in predicate
'$lgt_valid_predicate_property'(built_in).
% predicate is an alias of another predicate
'$lgt_valid_predicate_property'(alias_of(_)).
% entity where the predicate alias is declared
'$lgt_valid_predicate_property'(alias_declared_in(_)).
% clauses for the predicate can be defined within multiple entities
'$lgt_valid_predicate_property'((multifile)).
% predicate version of a non-terminal
'$lgt_valid_predicate_property'(non_terminal(_)).
% calls to the predicate are synchronized
'$lgt_valid_predicate_property'(synchronized).
% the remaining properties are available only when the entities are compiled with the "source_data" flag turned on
% mode/2 predicate information (predicates can have more than one mode)
'$lgt_valid_predicate_property'(mode(_, _)).
% info/2 predicate information
'$lgt_valid_predicate_property'(info(_)).
% number of predicate clauses
'$lgt_valid_predicate_property'(number_of_clauses(_)).
% number of predicate rules
'$lgt_valid_predicate_property'(number_of_rules(_)).
% entity containing the predicate scope directive plus declaration line
'$lgt_valid_predicate_property'(declared_in(_, _)).
% object or category containing the predicate definition plus definition line
'$lgt_valid_predicate_property'(defined_in(_, _)).
% object or category containing the inherited but overridden predicate definition plus definition line
'$lgt_valid_predicate_property'(redefined_from(_, _)).
% entity where the predicate alias is declared plus declaration line
'$lgt_valid_predicate_property'(alias_declared_in(_, _)).
% predicate is an auxiliary predicate
'$lgt_valid_predicate_property'(auxiliary).
% predicate definition is inlined
'$lgt_valid_predicate_property'(inline).
% predicate definition is recursive
'$lgt_valid_predicate_property'(recursive).
% '$lgt_valid_protocol_property'(@nonvar)
% built-in entity
'$lgt_valid_protocol_property'(built_in).
% dynamic entity (can be abolished at runtime)
'$lgt_valid_protocol_property'((dynamic)).
% static entity
'$lgt_valid_protocol_property'(static).
% entity compiled in debug mode
'$lgt_valid_protocol_property'(debugging).
% list of predicate indicators of public predicates declared in the entity
'$lgt_valid_protocol_property'(public(_)).
% list of predicate indicators of protected predicates declared in the entity
'$lgt_valid_protocol_property'(protected(_)).
% list of predicate indicators of private predicates declared in the entity
'$lgt_valid_protocol_property'(private(_)).
% list of declaration properties for a predicate declared in the entity
'$lgt_valid_protocol_property'(declares(_, _)).
% list of properties for a predicate alias declared in the entity
'$lgt_valid_protocol_property'(alias(_, _)).
% source data available for the entity
'$lgt_valid_protocol_property'(source_data).
% the remaining properties are available only when the entities are compiled with the "source_data" flag turned on
% list of pairs with user-defined protocol documentation
'$lgt_valid_protocol_property'(info(_)).
% source file absolute path
'$lgt_valid_protocol_property'(file(_)).
% source file basename and directory
'$lgt_valid_protocol_property'(file(_, _)).
% start and end lines in a source file
'$lgt_valid_protocol_property'(lines(_, _)).
% start and end lines in a source file of the entity opening directive
'$lgt_valid_protocol_property'(directive(_, _)).
% '$lgt_valid_category_property'(@nonvar)
% category properties include all protocol properties
'$lgt_valid_category_property'(Property) :-
'$lgt_valid_protocol_property'(Property), !.
% messages sent from the object using the ::/2 control construct generate events
'$lgt_valid_category_property'(events).
% list of definition properties for a predicate defined in the category
'$lgt_valid_category_property'(defines(_, _)).
% list of definition properties for a multifile predicate defined in contributing entities
'$lgt_valid_category_property'(includes(_, _, _)).
% list of definition properties for a multifile predicate defined for other entities
'$lgt_valid_category_property'(provides(_, _, _)).
% list of calling properties for a predicate called in the entity
'$lgt_valid_category_property'(calls(_, _)).
% list of updating properties for a dynamic predicate updated in the entity
'$lgt_valid_category_property'(updates(_, _)).
% number of predicate clauses (including both user-defined and auxiliary clauses)
'$lgt_valid_category_property'(number_of_clauses(_)).
% number of predicate rules (including both user-defined and auxiliary clauses)
'$lgt_valid_category_property'(number_of_rules(_)).
% number of user-defined predicate clauses
'$lgt_valid_category_property'(number_of_user_clauses(_)).
% number of user-defined predicate rules
'$lgt_valid_category_property'(number_of_user_rules(_)).
% '$lgt_valid_object_property'(@nonvar)
% object properties include all category and protocol properties
'$lgt_valid_object_property'(Property) :-
'$lgt_valid_category_property'(Property), !.
% object contains calls to the built-in multi-threading predicates
'$lgt_valid_object_property'(threaded).
% object allows the use of the <2 debugging control construct
'$lgt_valid_object_property'(context_switching_calls).
% object supports dynamic declaration of new predicates
'$lgt_valid_object_property'(dynamic_declarations).
% object can be complemented by categories (old, deprecated, Logtalk 2.x property)
'$lgt_valid_object_property'(complements).
% object can be complemented by categories
'$lgt_valid_object_property'(complements(_)).
% object resulted from the compilation of a Prolog module
'$lgt_valid_object_property'(module).
% '$lgt_valid_flag'(@nonvar)
%
% true if the argument is a valid Logtalk flag name
% meta-lint compilation flag
'$lgt_valid_flag'(linter).
% lint compilation flags
'$lgt_valid_flag'(always_true_or_false_goals).
'$lgt_valid_flag'(arithmetic_expressions).
'$lgt_valid_flag'(catchall_catch).
'$lgt_valid_flag'(conditionals).
'$lgt_valid_flag'(deprecated).
'$lgt_valid_flag'(disjunctions).
'$lgt_valid_flag'(duplicated_clauses).
'$lgt_valid_flag'(duplicated_directives).
'$lgt_valid_flag'(encodings).
'$lgt_valid_flag'(general).
'$lgt_valid_flag'(grammar_rules).
'$lgt_valid_flag'(lambda_variables).
'$lgt_valid_flag'(left_recursion).
'$lgt_valid_flag'(missing_directives).
'$lgt_valid_flag'(naming).
'$lgt_valid_flag'(portability).
'$lgt_valid_flag'(redefined_built_ins).
'$lgt_valid_flag'(redefined_operators).
'$lgt_valid_flag'(singleton_variables).
'$lgt_valid_flag'(steadfastness).
'$lgt_valid_flag'(suspicious_calls).
'$lgt_valid_flag'(tail_recursive).
'$lgt_valid_flag'(trivial_goal_fails).
'$lgt_valid_flag'(undefined_predicates).
'$lgt_valid_flag'(unknown_entities).
'$lgt_valid_flag'(unknown_predicates).
% optional features compilation flags
'$lgt_valid_flag'(complements).
'$lgt_valid_flag'(context_switching_calls).
'$lgt_valid_flag'(dynamic_declarations).
'$lgt_valid_flag'(events).
% other compilation flags
'$lgt_valid_flag'(clean).
'$lgt_valid_flag'(code_prefix).
'$lgt_valid_flag'(debug).
'$lgt_valid_flag'(hook).
'$lgt_valid_flag'(optimize).
'$lgt_valid_flag'(relative_to).
'$lgt_valid_flag'(reload).
'$lgt_valid_flag'(report).
'$lgt_valid_flag'(scratch_directory).
'$lgt_valid_flag'(source_data).
% read-only compilation flags
'$lgt_valid_flag'(version_data).
% startup flags
'$lgt_valid_flag'(settings_file).
% backend Prolog compiler information
'$lgt_valid_flag'(prolog_compatible_version).
'$lgt_valid_flag'(prolog_dialect).
'$lgt_valid_flag'(prolog_version).
'$lgt_valid_flag'(underscore_variables).
% features requiring specific backend Prolog compiler support
'$lgt_valid_flag'(coinduction).
'$lgt_valid_flag'(encoding_directive).
'$lgt_valid_flag'(engines).
'$lgt_valid_flag'(modules).
'$lgt_valid_flag'(tabling).
'$lgt_valid_flag'(threads).
'$lgt_valid_flag'(unicode).
% backend Prolog compiler and loader options
'$lgt_valid_flag'(prolog_compiler).
'$lgt_valid_flag'(prolog_loader).
% internal flags
'$lgt_valid_flag'('$relative_to').
% '$lgt_read_only_flag'(@nonvar)
%
% true if the argument is a read only Logtalk flag name
% Logtalk version flag
'$lgt_read_only_flag'(version_data).
% startup flags
'$lgt_read_only_flag'(settings_file).
% backend Prolog compiler features
'$lgt_read_only_flag'(coinduction).
'$lgt_read_only_flag'(encoding_directive).
'$lgt_read_only_flag'(engines).
'$lgt_read_only_flag'(modules).
'$lgt_read_only_flag'(prolog_compatible_version).
'$lgt_read_only_flag'(prolog_dialect).
'$lgt_read_only_flag'(prolog_version).
'$lgt_read_only_flag'(tabling).
'$lgt_read_only_flag'(threads).
'$lgt_read_only_flag'(unicode).
% '$lgt_valid_flag_value'(@atom, @nonvar)
% meta-lint compilation flag
'$lgt_valid_flag_value'(linter, on) :- !.
'$lgt_valid_flag_value'(linter, default) :- !.
'$lgt_valid_flag_value'(linter, off) :- !.
% lint compilation flags
'$lgt_valid_flag_value'(always_true_or_false_goals, silent) :- !.
'$lgt_valid_flag_value'(always_true_or_false_goals, warning) :- !.
'$lgt_valid_flag_value'(arithmetic_expressions, silent) :- !.
'$lgt_valid_flag_value'(arithmetic_expressions, warning) :- !.
'$lgt_valid_flag_value'(catchall_catch, silent) :- !.
'$lgt_valid_flag_value'(catchall_catch, warning) :- !.
'$lgt_valid_flag_value'(conditionals, silent) :- !.
'$lgt_valid_flag_value'(conditionals, warning) :- !.
'$lgt_valid_flag_value'(deprecated, silent) :- !.
'$lgt_valid_flag_value'(deprecated, warning) :- !.
'$lgt_valid_flag_value'(disjunctions, silent) :- !.
'$lgt_valid_flag_value'(disjunctions, warning) :- !.
'$lgt_valid_flag_value'(duplicated_clauses, silent) :- !.
'$lgt_valid_flag_value'(duplicated_clauses, warning) :- !.
'$lgt_valid_flag_value'(duplicated_directives, silent) :- !.
'$lgt_valid_flag_value'(duplicated_directives, warning) :- !.
'$lgt_valid_flag_value'(encodings, silent) :- !.
'$lgt_valid_flag_value'(encodings, warning) :- !.
'$lgt_valid_flag_value'(general, silent) :- !.
'$lgt_valid_flag_value'(general, warning) :- !.
'$lgt_valid_flag_value'(grammar_rules, silent) :- !.
'$lgt_valid_flag_value'(grammar_rules, warning) :- !.
'$lgt_valid_flag_value'(lambda_variables, silent) :- !.
'$lgt_valid_flag_value'(lambda_variables, warning) :- !.
'$lgt_valid_flag_value'(left_recursion, silent) :- !.
'$lgt_valid_flag_value'(left_recursion, warning) :- !.
'$lgt_valid_flag_value'(missing_directives, silent) :- !.
'$lgt_valid_flag_value'(missing_directives, warning) :- !.
'$lgt_valid_flag_value'(naming, silent) :- !.
'$lgt_valid_flag_value'(naming, warning) :- !.
'$lgt_valid_flag_value'(portability, silent) :- !.
'$lgt_valid_flag_value'(portability, warning) :- !.
'$lgt_valid_flag_value'(redefined_built_ins, silent) :- !.
'$lgt_valid_flag_value'(redefined_built_ins, warning) :- !.
'$lgt_valid_flag_value'(redefined_operators, silent) :- !.
'$lgt_valid_flag_value'(redefined_operators, warning) :- !.
'$lgt_valid_flag_value'(singleton_variables, silent) :- !.
'$lgt_valid_flag_value'(singleton_variables, warning) :- !.
'$lgt_valid_flag_value'(steadfastness, silent) :- !.
'$lgt_valid_flag_value'(steadfastness, warning) :- !.
'$lgt_valid_flag_value'(suspicious_calls, silent) :- !.
'$lgt_valid_flag_value'(suspicious_calls, warning) :- !.
'$lgt_valid_flag_value'(tail_recursive, silent) :- !.
'$lgt_valid_flag_value'(tail_recursive, warning) :- !.
'$lgt_valid_flag_value'(trivial_goal_fails, silent) :- !.
'$lgt_valid_flag_value'(trivial_goal_fails, warning) :- !.
'$lgt_valid_flag_value'(underscore_variables, dont_care) :- !.
'$lgt_valid_flag_value'(underscore_variables, singletons) :- !.
'$lgt_valid_flag_value'(undefined_predicates, silent) :- !.
'$lgt_valid_flag_value'(undefined_predicates, warning) :- !.
'$lgt_valid_flag_value'(undefined_predicates, error) :- !.
'$lgt_valid_flag_value'(unknown_entities, silent) :- !.
'$lgt_valid_flag_value'(unknown_entities, warning) :- !.
'$lgt_valid_flag_value'(unknown_predicates, silent) :- !.
'$lgt_valid_flag_value'(unknown_predicates, warning) :- !.
'$lgt_valid_flag_value'(unknown_predicates, error) :- !.
% optional features compilation flags
'$lgt_valid_flag_value'(complements, allow) :- !.
'$lgt_valid_flag_value'(complements, restrict) :- !.
'$lgt_valid_flag_value'(complements, deny) :- !.
'$lgt_valid_flag_value'(context_switching_calls, allow) :- !.
'$lgt_valid_flag_value'(context_switching_calls, deny) :- !.
'$lgt_valid_flag_value'(dynamic_declarations, allow) :- !.
'$lgt_valid_flag_value'(dynamic_declarations, deny) :- !.
'$lgt_valid_flag_value'(events, allow) :- !.
'$lgt_valid_flag_value'(events, deny) :- !.
% other compilation flags
'$lgt_valid_flag_value'(clean, on) :- !.
'$lgt_valid_flag_value'(clean, off) :- !.
'$lgt_valid_flag_value'(code_prefix, Prefix) :-
atom(Prefix),
atom_length(Prefix, 1).
'$lgt_valid_flag_value'(debug, on) :- !.
'$lgt_valid_flag_value'(debug, off) :- !.
'$lgt_valid_flag_value'(hook, Obj) :-
callable(Obj).
'$lgt_valid_flag_value'(optimize, on) :- !.
'$lgt_valid_flag_value'(optimize, off) :- !.
'$lgt_valid_flag_value'(relative_to, Directory) :-
atom(Directory).
'$lgt_valid_flag_value'(reload, always) :- !.
'$lgt_valid_flag_value'(reload, changed) :- !.
'$lgt_valid_flag_value'(reload, skip) :- !.
'$lgt_valid_flag_value'(report, on) :- !.
'$lgt_valid_flag_value'(report, warnings) :- !.
'$lgt_valid_flag_value'(report, off) :- !.
'$lgt_valid_flag_value'(scratch_directory, Directory) :-
callable(Directory).
'$lgt_valid_flag_value'(source_data, on) :- !.
'$lgt_valid_flag_value'(source_data, off) :- !.
% internal flags
'$lgt_valid_flag_value'('$relative_to', Directory) :-
% internal flag; just for documenting value type
atom(Directory).
% backend Prolog compiler and loader options
'$lgt_valid_flag_value'(prolog_compiler, Options) :-
'$lgt_is_list'(Options).
'$lgt_valid_flag_value'(prolog_loader, Options) :-
'$lgt_is_list'(Options).
% Logtalk version flag
'$lgt_valid_flag_value'(version_data, Version) :-
compound(Version),
functor(Version, logtalk, 4).
% startup flags
'$lgt_valid_flag_value'(settings_file, allow) :- !.
'$lgt_valid_flag_value'(settings_file, restrict) :- !.
'$lgt_valid_flag_value'(settings_file, deny) :- !.
'$lgt_valid_flag_value'(prolog_dialect, Dialect) :-
atom(Dialect).
'$lgt_valid_flag_value'(prolog_version, Version) :-
compound(Version),
functor(Version, v, 3).
'$lgt_valid_flag_value'(prolog_compatible_version, Version) :-
compound(Version),
functor(Version, v, 3).
% backend Prolog compiler features
'$lgt_valid_flag_value'(coinduction, supported) :- !.
'$lgt_valid_flag_value'(coinduction, unsupported) :- !.
'$lgt_valid_flag_value'(encoding_directive, full) :- !.
'$lgt_valid_flag_value'(encoding_directive, source) :- !.
'$lgt_valid_flag_value'(encoding_directive, unsupported) :- !.
'$lgt_valid_flag_value'(engines, supported) :- !.
'$lgt_valid_flag_value'(engines, unsupported) :- !.
'$lgt_valid_flag_value'(modules, supported) :- !.
'$lgt_valid_flag_value'(modules, unsupported) :- !.
'$lgt_valid_flag_value'(tabling, supported) :- !.
'$lgt_valid_flag_value'(tabling, unsupported) :- !.
'$lgt_valid_flag_value'(threads, supported) :- !.
'$lgt_valid_flag_value'(threads, unsupported) :- !.
'$lgt_valid_flag_value'(unicode, full) :- !.
'$lgt_valid_flag_value'(unicode, bmp) :- !.
'$lgt_valid_flag_value'(unicode, unsupported) :- !.
% '$lgt_linter_flag'(?atom)
'$lgt_linter_flag'(always_true_or_false_goals).
'$lgt_linter_flag'(arithmetic_expressions).
'$lgt_linter_flag'(catchall_catch).
'$lgt_linter_flag'(conditionals).
'$lgt_linter_flag'(deprecated).
'$lgt_linter_flag'(disjunctions).
'$lgt_linter_flag'(duplicated_clauses).
'$lgt_linter_flag'(duplicated_directives).
'$lgt_linter_flag'(encodings).
'$lgt_linter_flag'(general).
'$lgt_linter_flag'(grammar_rules).
'$lgt_linter_flag'(lambda_variables).
'$lgt_linter_flag'(left_recursion).
'$lgt_linter_flag'(missing_directives).
'$lgt_linter_flag'(naming).
'$lgt_linter_flag'(portability).
'$lgt_linter_flag'(redefined_built_ins).
'$lgt_linter_flag'(redefined_operators).
'$lgt_linter_flag'(singleton_variables).
'$lgt_linter_flag'(steadfastness).
'$lgt_linter_flag'(suspicious_calls).
'$lgt_linter_flag'(tail_recursive).
'$lgt_linter_flag'(trivial_goal_fails).
'$lgt_linter_flag'(undefined_predicates).
'$lgt_linter_flag'(unknown_entities).
'$lgt_linter_flag'(unknown_predicates).
% '$lgt_valid_remark'(@term)
%
% valid predicate remark documentation on info/1-2 directives
'$lgt_valid_remark'(Topic - Text) :-
atom(Topic),
atom(Text).
% '$lgt_valid_predicate_allocation'(@nonvar)
%
% valid predicate allocation on info/2 directive
% predicate defined in the object containing its scope directive
'$lgt_valid_predicate_allocation'(container).
% predicate should be defined in the descendant objects
'$lgt_valid_predicate_allocation'(descendants).
% predicate should be defined in the class instances
'$lgt_valid_predicate_allocation'(instances).
% predicate should be defined in the class and its subclasses
'$lgt_valid_predicate_allocation'(classes).
% predicate should be defined in the class subclasses
'$lgt_valid_predicate_allocation'(subclasses).
% no restrictions on where the predicate should be defined
'$lgt_valid_predicate_allocation'(any).
% '$lgt_valid_predicate_redefinition'(@nonvar)
%
% valid predicate redefinition on info/2 directive
% predicate should not be redefined
'$lgt_valid_predicate_redefinition'(never).
% predicate can be freely redefined
'$lgt_valid_predicate_redefinition'(free).
% predicate redefinition must call the inherited definition
'$lgt_valid_predicate_redefinition'(specialize).
% predicate redefinition must call the inherited definition as the first body goal
'$lgt_valid_predicate_redefinition'(call_super_first).
% predicate redefinition must call the inherited definition as the last body goal
'$lgt_valid_predicate_redefinition'(call_super_last).
% '$lgt_valid_predicate_exception'(@term)
%
% valid predicate exception documentation on info/2 directive
'$lgt_valid_predicate_exception'(Description - Term) :-
atom(Description),
nonvar(Term).
% '$lgt_valid_predicate_call_example'(@term, +atom, +integer)
%
% valid predicate call example documentation on info/2 directive
'$lgt_valid_predicate_call_example'((Description - Call - {Bindings}), Functor, Arity) :-
atom(Description),
nonvar(Call),
functor(Pred, Functor, Arity),
Call = Pred,
nonvar(Bindings),
( Bindings == no -> true
; Bindings == yes -> true
; Bindings == false -> true
; Bindings == true -> true
; '$lgt_valid_example_var_bindings'(Bindings)
).
'$lgt_valid_example_var_bindings'((Binding, Bindings)) :-
!,
'$lgt_valid_example_var_binding'(Binding),
'$lgt_valid_example_var_bindings'(Bindings).
'$lgt_valid_example_var_bindings'(Binding) :-
'$lgt_valid_example_var_binding'(Binding).
'$lgt_valid_example_var_binding'(Binding) :-
nonvar(Binding),
Binding = (Var = _),
var(Var).
% Logtalk built-in predicates
%
% '$lgt_logtalk_built_in_predicate'(?callable, ?callable)
%
% the second argument is either a meta-predicate template
% (when aplicable) or the atom "no"
% message sending and context switching control constructs
'$lgt_logtalk_built_in_predicate'(_ :: _, no).
'$lgt_logtalk_built_in_predicate'(_ << _, no).
% compiling and loading predicates
'$lgt_logtalk_built_in_predicate'(logtalk_compile(_,_,_), no).
'$lgt_logtalk_built_in_predicate'(logtalk_compile(_, _), no).
'$lgt_logtalk_built_in_predicate'(logtalk_load(_), no).
'$lgt_logtalk_built_in_predicate'(logtalk_load(_, _), no).
'$lgt_logtalk_built_in_predicate'(logtalk_make, no).
'$lgt_logtalk_built_in_predicate'(logtalk_make(_), no).
'$lgt_logtalk_built_in_predicate'(logtalk_load_context(_, _), no).
'$lgt_logtalk_built_in_predicate'(logtalk_library_path(_, _), no).
'$lgt_logtalk_built_in_predicate'(logtalk_make_target_action(_), no).
% entity properties
'$lgt_logtalk_built_in_predicate'(protocol_property(_, _), no).
'$lgt_logtalk_built_in_predicate'(category_property(_, _), no).
'$lgt_logtalk_built_in_predicate'(object_property(_, _), no).
% entity enumeration
'$lgt_logtalk_built_in_predicate'(current_protocol(_), no).
'$lgt_logtalk_built_in_predicate'(current_category(_), no).
'$lgt_logtalk_built_in_predicate'(current_object(_), no).
% entity creation predicates
'$lgt_logtalk_built_in_predicate'(create_object(_, _, _, _), no).
'$lgt_logtalk_built_in_predicate'(create_category(_, _, _, _), no).
'$lgt_logtalk_built_in_predicate'(create_protocol(_, _, _), no).
% entity abolishing predicates
'$lgt_logtalk_built_in_predicate'(abolish_object(_), no).
'$lgt_logtalk_built_in_predicate'(abolish_category(_), no).
'$lgt_logtalk_built_in_predicate'(abolish_protocol(_), no).
% entity relations
'$lgt_logtalk_built_in_predicate'(implements_protocol(_, _), no).
'$lgt_logtalk_built_in_predicate'(implements_protocol(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(imports_category(_, _), no).
'$lgt_logtalk_built_in_predicate'(imports_category(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(instantiates_class(_, _), no).
'$lgt_logtalk_built_in_predicate'(instantiates_class(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(specializes_class(_, _), no).
'$lgt_logtalk_built_in_predicate'(specializes_class(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(extends_protocol(_, _), no).
'$lgt_logtalk_built_in_predicate'(extends_protocol(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(extends_object(_, _), no).
'$lgt_logtalk_built_in_predicate'(extends_object(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(extends_category(_, _), no).
'$lgt_logtalk_built_in_predicate'(extends_category(_, _, _), no).
'$lgt_logtalk_built_in_predicate'(complements_object(_, _), no).
% protocol conformance
'$lgt_logtalk_built_in_predicate'(conforms_to_protocol(_, _), no).
'$lgt_logtalk_built_in_predicate'(conforms_to_protocol(_, _, _), no).
% events
'$lgt_logtalk_built_in_predicate'(abolish_events(_, _, _, _, _), no).
'$lgt_logtalk_built_in_predicate'(define_events(_, _, _, _, _), no).
'$lgt_logtalk_built_in_predicate'(current_event(_, _, _, _, _), no).
% flags
'$lgt_logtalk_built_in_predicate'(current_logtalk_flag(_, _), no).
'$lgt_logtalk_built_in_predicate'(set_logtalk_flag(_, _), no).
'$lgt_logtalk_built_in_predicate'(create_logtalk_flag(_, _, _), no).
% multi-threading predicates
'$lgt_logtalk_built_in_predicate'(threaded(_), threaded(0)).
'$lgt_logtalk_built_in_predicate'(threaded_call(_, _), threaded_call(0, *)).
'$lgt_logtalk_built_in_predicate'(threaded_call(_), threaded_call(0)).
'$lgt_logtalk_built_in_predicate'(threaded_once(_, _), threaded_once(0, *)).
'$lgt_logtalk_built_in_predicate'(threaded_once(_), threaded_once(0)).
'$lgt_logtalk_built_in_predicate'(threaded_ignore(_), threaded_ignore(0)).
'$lgt_logtalk_built_in_predicate'(threaded_exit(_, _), threaded_exit((::), *)).
'$lgt_logtalk_built_in_predicate'(threaded_exit(_), threaded_exit((::))).
'$lgt_logtalk_built_in_predicate'(threaded_peek(_, _), threaded_peek((::), *)).
'$lgt_logtalk_built_in_predicate'(threaded_peek(_), threaded_peek((::))).
'$lgt_logtalk_built_in_predicate'(threaded_cancel(_), threaded_cancel(*)).
'$lgt_logtalk_built_in_predicate'(threaded_wait(_), no).
'$lgt_logtalk_built_in_predicate'(threaded_notify(_), no).
% threaded engines predicates
'$lgt_logtalk_built_in_predicate'(threaded_engine_create(_, _, _), threaded_engine_create(*, 0, *)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_destroy(_), threaded_engine_destroy(*)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_self(_), threaded_engine_self(*)).
'$lgt_logtalk_built_in_predicate'(threaded_engine(_), threaded_engine(*)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_next(_, _), threaded_engine_next(*, *)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_next_reified(_, _), threaded_engine_next_reified(*, *)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_yield(_), threaded_engine_yield(*)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_post(_, _), threaded_engine_post(*, *)).
'$lgt_logtalk_built_in_predicate'(threaded_engine_fetch(_), threaded_engine_fetch(*)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DCG rule conversion
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_dcg_rule'(@grammar_rule, -clause, @compilation_context)
%
% converts a grammar rule into a normal clause
'$lgt_dcg_rule'((RHead --> _), _, _) :-
var(RHead),
throw(instantiation_error).
'$lgt_dcg_rule'((RHead, _ --> _), _, _) :-
var(RHead),
throw(instantiation_error).
'$lgt_dcg_rule'((Entity::NonTerminal, Terminals --> GRBody), (Entity::Head :- Body), Ctx) :-
!,
'$lgt_check'(object_identifier, Entity),
'$lgt_dcg_rule'((NonTerminal, Terminals --> GRBody), (Head :- Body), Ctx).
'$lgt_dcg_rule'((':'(Module, NonTerminal), Terminals --> GRBody), (':'(Module, Head) :- Body), Ctx) :-
!,
'$lgt_check'(module_identifier, Module),
'$lgt_dcg_rule'((NonTerminal, Terminals --> GRBody), (Head :- Body), Ctx).
'$lgt_dcg_rule'((phrase(_), _ --> _), _, _) :-
throw(permission_error(modify, built_in_non_terminal, phrase//1)).
'$lgt_dcg_rule'((NonTerminal, _ --> _), _, _) :-
functor(NonTerminal, call, Arity),
Arity >= 1,
throw(permission_error(modify, built_in_non_terminal, call//Arity)).
'$lgt_dcg_rule'((NonTerminal, Terminals --> GRBody), _, Ctx) :-
once((
'$lgt_variant'(GRBody, NonTerminal)
; GRBody = (GRFirst, _),
'$lgt_variant'(GRFirst, NonTerminal)
)),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(left_recursion, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(left_recursion),
left_recursion(File, Lines, Type, Entity, (NonTerminal, Terminals --> GRBody))
),
fail.
'$lgt_dcg_rule'((NonTerminal, Terminals --> GRBody), (Head :- Body), Ctx) :-
!,
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Head),
'$lgt_dcg_body'(GRBody, S0, S1, Goal1, Ctx),
'$lgt_dcg_terminals'(Terminals, S, S1, Goal2),
Body = (Goal1, Goal2),
functor(NonTerminal, Functor, Arity),
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
\+ '$lgt_pp_defines_non_terminal_'(Functor, Arity, _) ->
ExtArity is Arity + 2,
assertz('$lgt_pp_defines_non_terminal_'(Functor, Arity, ExtArity))
; true
).
'$lgt_dcg_rule'((Entity::NonTerminal --> GRBody), (Entity::Head :- Body), Ctx) :-
!,
'$lgt_check'(object_identifier, Entity),
'$lgt_dcg_rule'((NonTerminal --> GRBody), (Head :- Body), Ctx).
'$lgt_dcg_rule'((':'(Module, NonTerminal) --> GRBody), (':'(Module, Head) :- Body), Ctx) :-
!,
'$lgt_check'(module_identifier, Module),
'$lgt_dcg_rule'((NonTerminal --> GRBody), (Head :- Body), Ctx).
'$lgt_dcg_rule'((phrase(_) --> _), _, _) :-
throw(permission_error(modify, built_in_non_terminal, phrase//1)).
'$lgt_dcg_rule'((NonTerminal --> _), _, _) :-
functor(NonTerminal, call, Arity),
Arity >= 1,
throw(permission_error(modify, built_in_non_terminal, call//Arity)).
'$lgt_dcg_rule'((eos --> _), _, _) :-
throw(permission_error(modify, built_in_non_terminal, eos//0)).
'$lgt_dcg_rule'((NonTerminal --> GRBody), _, Ctx) :-
once((
'$lgt_variant'(GRBody, NonTerminal)
; GRBody = (GRFirst, _),
'$lgt_variant'(GRFirst, NonTerminal)
)),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(left_recursion, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(left_recursion),
left_recursion(File, Lines, Type, Entity, (NonTerminal --> GRBody))
),
fail.
'$lgt_dcg_rule'((NonTerminal --> GRBody), (Head :- Body), Ctx) :-
!,
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Head),
'$lgt_dcg_body'(GRBody, S0, S, Body, Ctx),
functor(NonTerminal, Functor, Arity),
( '$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
\+ '$lgt_pp_defines_non_terminal_'(Functor, Arity, _) ->
ExtArity is Arity + 2,
assertz('$lgt_pp_defines_non_terminal_'(Functor, Arity, ExtArity))
; true
).
'$lgt_dcg_rule'(Term, _, _) :-
throw(type_error(grammar_rule, Term)).
% '$lgt_dcg_non_terminal'(+callable, @var, @var, -goal)
%
% translates a grammar goal non-terminal
'$lgt_dcg_non_terminal'(NonTerminal, _, _, _) :-
'$lgt_check'(callable, NonTerminal),
'$lgt_pp_protocol_'(_, _, _, _, _),
% protocols cannot contain non-terminal definitions
functor(NonTerminal, Functor, Arity),
throw(permission_error(define, non_terminal, Functor//Arity)).
'$lgt_dcg_non_terminal'((_ ; _), _, _, _) :-
throw(permission_error(modify, control_construct, (;)/2)).
'$lgt_dcg_non_terminal'((_ -> _), _, _, _) :-
throw(permission_error(modify, control_construct, (->)/2)).
'$lgt_dcg_non_terminal'('*->'(_, _), _, _, _) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
throw(permission_error(modify, control_construct, (*->)/2)).
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Goal) :-
NonTerminal =.. NonTerminalUniv,
'$lgt_append'(NonTerminalUniv, [S0, S], GoalUniv),
Goal =.. GoalUniv.
% '$lgt_dcg_terminals'(+list, @var, @var, -goal)
%
% translates a list of terminals
'$lgt_dcg_terminals'(Terminals, S0, S, S0 = List) :-
'$lgt_check'(list, Terminals),
'$lgt_append'(Terminals, S, List).
% '$lgt_dcg_msg'(@dcgbody @object_identifier, @var, @var, -body)
%
% translates a grammar rule message to an object into a predicate message
'$lgt_dcg_msg'(Var, Obj, S0, S, phrase(Obj::Var, S0, S)) :-
var(Var),
!.
'$lgt_dcg_msg'('*->'(GRIf, GRThen), Obj, S0, S, '*->'(If, Then)) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_dcg_msg'(GRIf, Obj, S0, S1, If),
'$lgt_dcg_msg'(GRThen, Obj, S1, S, Then).
'$lgt_dcg_msg'((GRIf -> GRThen), Obj, S0, S, (If -> Then)) :-
!,
'$lgt_dcg_msg'(GRIf, Obj, S0, S1, If),
'$lgt_dcg_msg'(GRThen, Obj, S1, S, Then).
'$lgt_dcg_msg'((GREither; GROr), Obj, S0, S, (Either; Or)) :-
!,
'$lgt_dcg_msg'(GREither, Obj, S0, S, Either),
'$lgt_dcg_msg'(GROr, Obj, S0, S, Or).
'$lgt_dcg_msg'((GRFirst, GRSecond), Obj, S0, S, (First, Second)) :-
!,
'$lgt_dcg_msg'(GRFirst, Obj, S0, S1, First),
'$lgt_dcg_msg'(GRSecond, Obj, S1, S, Second).
'$lgt_dcg_msg'(!, _, S0, S, (!, (S0 = S))) :-
!.
'$lgt_dcg_msg'(NonTerminal, Obj, S0, S, Obj::Pred) :-
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Pred).
% '$lgt_dcg_self_msg'(@dcgbody, @var, @var, -body, -body)
%
% translates a grammar rule message to an object into a predicate message
'$lgt_dcg_self_msg'(Var, S0, S, phrase(::Var, S0, S)) :-
var(Var),
!.
'$lgt_dcg_self_msg'('*->'(GRIf, GRThen), S0, S, '*->'(If, Then)) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_dcg_self_msg'(GRIf, S0, S1, If),
'$lgt_dcg_self_msg'(GRThen, S1, S, Then).
'$lgt_dcg_self_msg'((GRIf -> GRThen), S0, S, (If -> Then)) :-
!,
'$lgt_dcg_self_msg'(GRIf, S0, S1, If),
'$lgt_dcg_self_msg'(GRThen, S1, S, Then).
'$lgt_dcg_self_msg'((GREither; GROr), S0, S, (Either; Or)) :-
!,
'$lgt_dcg_self_msg'(GREither, S0, S, Either),
'$lgt_dcg_self_msg'(GROr, S0, S, Or).
'$lgt_dcg_self_msg'((GRFirst, GRSecond), S0, S, (First, Second)) :-
!,
'$lgt_dcg_self_msg'(GRFirst, S0, S1, First),
'$lgt_dcg_self_msg'(GRSecond, S1, S, Second).
'$lgt_dcg_self_msg'(!, S0, S, (!, (S0 = S))) :-
!.
'$lgt_dcg_self_msg'(NonTerminal, S0, S, ::Pred) :-
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Pred).
% '$lgt_dcg_super_call'(@dcgbody, @var, @var, -body)
%
% translates a super call to a grammar rule in an ancestor entity
'$lgt_dcg_super_call'(Var, S0, S, phrase(^^Var, S0, S)) :-
var(Var),
!.
'$lgt_dcg_super_call'(NonTerminal, S0, S, ^^Pred) :-
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Pred).
% '$lgt_dcg_body'(@dcgbody, @var, @var, -body, @compilation_context)
%
% translates a grammar rule body into a Prolog clause body
'$lgt_dcg_body'(Var, S0, S, phrase(Var, S0, S), _) :-
var(Var),
!.
'$lgt_dcg_body'('$lgt_closure'(TFunctor, TArgs, ExCtx), S0, S, {TGoal}, _) :-
% pre-compiled closure (note that the closure may be called from a mapping
% predicate, which prevents us to use a difference list based solution to
% avoid the calls to append/3 and =../2 as that would fix the extra arguments
% in the goal on the first closure call and thus break the followup calls)
!,
'$lgt_append'(TArgs, [S0, S, ExCtx], FullArgs),
TGoal =.. [TFunctor| FullArgs].
'$lgt_dcg_body'(Free/Parameters>>Lambda, S0, S, call(Free/Parameters>>Lambda, S0, S), Ctx) :-
!,
'$lgt_check_lambda_expression'(Free/Parameters>>Lambda, Ctx),
( \+ Parameters \= [_, _] ->
true
; throw(representation_error(lambda_parameters))
).
'$lgt_dcg_body'(Parameters>>Lambda, S0, S, call(Parameters>>Lambda, S0, S), Ctx) :-
!,
'$lgt_check_lambda_expression'(Parameters>>Lambda, Ctx),
( \+ Parameters \= [_, _] ->
true
; throw(representation_error(lambda_parameters))
).
'$lgt_dcg_body'(Free/Lambda, S0, S, call(Free/Lambda, S0, S), Ctx) :-
!,
'$lgt_check_lambda_expression'(Free/Lambda, Ctx).
'$lgt_dcg_body'(Obj::RGoal, S0, S, CGoal, _) :-
!,
'$lgt_dcg_msg'(RGoal, Obj, S0, S, CGoal).
'$lgt_dcg_body'(::RGoal, S0, S, CGoal, _) :-
!,
'$lgt_dcg_self_msg'(RGoal, S0, S, CGoal).
'$lgt_dcg_body'(^^RGoal, S0, S, CGoal, _) :-
!,
'$lgt_dcg_super_call'(RGoal, S0, S, CGoal).
'$lgt_dcg_body'(Obj<
RGoal =.. RGoalUniv,
'$lgt_append'(RGoalUniv, [S0, S], GoalUniv),
Goal =.. GoalUniv,
CGoal = ':'(Module, Goal)
; CGoal = call(':'(Module,RGoal), S0, S)
).
'$lgt_dcg_body'((GRIfThen; GRElse), S0, S, (If -> Then; Else), Ctx) :-
nonvar(GRIfThen),
GRIfThen = (GRIf -> GRThen),
!,
'$lgt_dcg_body'(GRIf, S0, S1, If, Ctx),
'$lgt_dcg_body'(GRThen, S1, S, Then, Ctx),
'$lgt_dcg_body'(GRElse, S0, S, Else, Ctx).
'$lgt_dcg_body'((GRIfThen; GRElse), S0, S, ('*->'(If, Then); Else), Ctx) :-
nonvar(GRIfThen),
GRIfThen = '*->'(GRIf, GRThen),
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_dcg_body'(GRIf, S0, S1, If, Ctx),
'$lgt_dcg_body'(GRThen, S1, S, Then, Ctx),
'$lgt_dcg_body'(GRElse, S0, S, Else, Ctx).
'$lgt_dcg_body'((GREither; GROr), S0, S, (Either; Or), Ctx) :-
!,
'$lgt_dcg_body'(GREither, S0, S, Either0, Ctx),
'$lgt_fix_disjunction_left_side'(Either0, Either),
'$lgt_dcg_body'(GROr, S0, S, Or, Ctx).
'$lgt_dcg_body'('|'(GREither, GROr), S0, S, (Either; Or), Ctx) :-
!,
'$lgt_dcg_body'(GREither, S0, S, Either0, Ctx),
'$lgt_fix_disjunction_left_side'(Either0, Either),
'$lgt_dcg_body'(GROr, S0, S, Or, Ctx).
'$lgt_dcg_body'('*->'(GRIf, GRThen), _, _, _, Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
nonvar(GRIf),
\+ functor(GRIf, {}, 1),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(grammar_rules, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(grammar_rules),
unsound_construct_in_grammar_rule(File, Lines, Type, Entity, '*->'(GRIf, GRThen))
),
fail.
'$lgt_dcg_body'('*->'(GRIf, GRThen), S0, S, '*->'(If, Then), Ctx) :-
'$lgt_predicate_property'('*->'(_, _), built_in),
!,
'$lgt_dcg_body'(GRIf, S0, S1, If, Ctx),
'$lgt_dcg_body'(GRThen, S1, S, Then, Ctx).
'$lgt_dcg_body'((GRIf -> GRThen), _, _, _, Ctx) :-
nonvar(GRIf),
\+ functor(GRIf, {}, 1),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(grammar_rules, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(grammar_rules),
unsound_construct_in_grammar_rule(File, Lines, Type, Entity, (GRIf -> GRThen))
),
fail.
'$lgt_dcg_body'((GRIf -> GRThen), S0, S, (If -> Then), Ctx) :-
!,
'$lgt_dcg_body'(GRIf, S0, S1, If, Ctx),
'$lgt_dcg_body'(GRThen, S1, S, Then, Ctx).
'$lgt_dcg_body'((GRFirst, GRSecond), S0, S, (First, Second), Ctx) :-
!,
'$lgt_dcg_body'(GRFirst, S0, S1, First, Ctx),
'$lgt_dcg_body'(GRSecond, S1, S, Second, Ctx).
'$lgt_dcg_body'(!, S0, S, (!, (S0 = S)), _) :-
!.
'$lgt_dcg_body'('{}', S0, S, (S0 = S), _) :-
!.
'$lgt_dcg_body'({Goal}, S0, S, (call(Goal), (S0 = S)), _) :-
var(Goal),
!.
'$lgt_dcg_body'({Goal}, S0, S, (Goal, (S0 = S)), _) :-
!,
'$lgt_check'(callable, Goal).
'$lgt_dcg_body'(\+ GRBody, _, _, _, Ctx) :-
nonvar(GRBody),
\+ functor(GRBody, {}, 1),
'$lgt_comp_ctx_mode'(Ctx, compile(_,_,_)),
'$lgt_compiler_flag'(grammar_rules, warning),
'$lgt_source_file_context'(File, Lines, Type, Entity),
'$lgt_increment_compiling_warnings_counter',
'$lgt_print_message'(
warning(grammar_rules),
unsound_construct_in_grammar_rule(File, Lines, Type, Entity, \+ GRBody)
),
fail.
'$lgt_dcg_body'(\+ GRBody, S0, S, (\+ Goal, (S0 = S)), Ctx) :-
!,
'$lgt_dcg_body'(GRBody, S0, _, Goal, Ctx).
'$lgt_dcg_body'(catch(GRGoal, Catcher, GRRecovery), S0, S, catch(Goal, Catcher, Recovery), Ctx) :-
!,
'$lgt_dcg_body'(GRGoal, S0, S, Goal, Ctx),
'$lgt_dcg_body'(GRRecovery, S0, S, Recovery, Ctx).
'$lgt_dcg_body'(phrase(GRBody), S0, S, phrase(GRBody, S0, S), _) :-
!.
'$lgt_dcg_body'(eos, S0, S, (S0 = [], S = []), _) :-
!.
'$lgt_dcg_body'(GRBody, S0, S, Goal, _) :-
functor(GRBody, call, Arity),
Arity >= 1,
!,
GRBody =.. [call, Closure| ExtraArgs],
'$lgt_check'(var_or_callable, Closure),
'$lgt_append'(ExtraArgs, [S0, S], FullArgs),
% translate to the internal '$lgt_callN'/2 predicate instead of the call/N control
% construct to avoid lint warnings about redundant uses of the control construct
Goal = '$lgt_callN'(Closure, FullArgs).
'$lgt_dcg_body'([], S0, S, (S0 = S), _) :-
!.
'$lgt_dcg_body'([T| Ts], S0, S, Goal, _) :-
!,
'$lgt_dcg_terminals'([T| Ts], S0, S, Goal).
'$lgt_dcg_body'(String, S0, S, Goal, _) :-
'$lgt_string'(String),
!,
'$lgt_string_codes'(String, Codes),
'$lgt_dcg_terminals'(Codes, S0, S, Goal).
'$lgt_dcg_body'(Alias, S0, S, Goal, Ctx) :-
'$lgt_pp_uses_non_terminal_'(Obj, Original, Alias, Pred, PredAlias, Ctx, _, _),
!,
% we must register here otherwise the non-terminal alias information would be lost
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
'$lgt_add_referenced_object_message'(Mode, Obj, Pred, PredAlias, Head),
'$lgt_dcg_body'(Obj::Original, S0, S, Goal, Ctx).
'$lgt_dcg_body'(Alias, S0, S, Goal, Ctx) :-
'$lgt_pp_use_module_non_terminal_'(Module, Original, Alias, Pred, PredAlias, Ctx, _, _),
!,
% we must register here otherwise the non-terminal alias information would be lost
'$lgt_comp_ctx'(Ctx, Head, _, _, _, _, _, _, _, _, _, Mode, _, _, _),
'$lgt_add_referenced_module_predicate'(Mode, Module, Pred, PredAlias, Head),
'$lgt_dcg_body'(':'(Module, Original), S0, S, Goal, Ctx).
'$lgt_dcg_body'(NonTerminal, S0, S, Goal, Ctx) :-
'$lgt_dcg_non_terminal'(NonTerminal, S0, S, Goal),
functor(NonTerminal, Functor, Arity),
'$lgt_comp_ctx'(Ctx, _, _, _, _, _, _, _, _, _, _, Mode, _, Lines, _),
( Mode = compile(_,_,_),
\+ '$lgt_pp_calls_non_terminal_'(Functor, Arity, _, Lines) ->
ExtArity is Arity + 2,
assertz('$lgt_pp_calls_non_terminal_'(Functor, Arity, ExtArity, Lines))
; true
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% table of ISO Prolog specified built-in predicates
%
% (used for portability checking)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_iso_spec_predicate'(?callable)
% control constructs
'$lgt_iso_spec_predicate'(true).
'$lgt_iso_spec_predicate'(fail).
'$lgt_iso_spec_predicate'(false).
'$lgt_iso_spec_predicate'(call(_)).
'$lgt_iso_spec_predicate'(call(_, _)).
'$lgt_iso_spec_predicate'(call(_, _, _)).
'$lgt_iso_spec_predicate'(call(_, _, _, _)).
'$lgt_iso_spec_predicate'(call(_, _, _, _, _)).
'$lgt_iso_spec_predicate'(call(_, _, _, _, _, _)).
'$lgt_iso_spec_predicate'(call(_, _, _, _, _, _, _)).
'$lgt_iso_spec_predicate'(call(_, _, _, _, _, _, _, _)).
'$lgt_iso_spec_predicate'(!).
'$lgt_iso_spec_predicate'((Goal; _)) :-
( var(Goal) ->
true
; Goal \= '*->'(_, _)
).
'$lgt_iso_spec_predicate'((_, _)).
'$lgt_iso_spec_predicate'((_ -> _)).
'$lgt_iso_spec_predicate'(catch(_, _, _)).
'$lgt_iso_spec_predicate'(throw(_)).
% term unification
'$lgt_iso_spec_predicate'((_ = _)).
'$lgt_iso_spec_predicate'((_ \= _)).
'$lgt_iso_spec_predicate'(unify_with_occurs_check(_, _)).
'$lgt_iso_spec_predicate'(subsumes_term(_, _)).
% term testing
'$lgt_iso_spec_predicate'(var(_)).
'$lgt_iso_spec_predicate'(nonvar(_)).
'$lgt_iso_spec_predicate'(atom(_)).
'$lgt_iso_spec_predicate'(atomic(_)).
'$lgt_iso_spec_predicate'(number(_)).
'$lgt_iso_spec_predicate'(integer(_)).
'$lgt_iso_spec_predicate'(float(_)).
'$lgt_iso_spec_predicate'(compound(_)).
'$lgt_iso_spec_predicate'(acyclic_term(_)).
'$lgt_iso_spec_predicate'(callable(_)).
'$lgt_iso_spec_predicate'(ground(_)).
% term comparison
'$lgt_iso_spec_predicate'((_ @=< _)).
'$lgt_iso_spec_predicate'((_ @< _)).
'$lgt_iso_spec_predicate'((_ @>= _)).
'$lgt_iso_spec_predicate'((_ @> _)).
'$lgt_iso_spec_predicate'((_ == _)).
'$lgt_iso_spec_predicate'((_ \== _)).
'$lgt_iso_spec_predicate'(compare(_, _, _)).
% term creation and decomposition
'$lgt_iso_spec_predicate'(functor(_, _, _)).
'$lgt_iso_spec_predicate'(arg(_, _, _)).
'$lgt_iso_spec_predicate'(_ =.. _).
'$lgt_iso_spec_predicate'(copy_term(_, _)).
'$lgt_iso_spec_predicate'(term_variables(_, _)).
% arithmetic evaluation
'$lgt_iso_spec_predicate'(_ is _).
% arithmetic comparison
'$lgt_iso_spec_predicate'((_ =< _)).
'$lgt_iso_spec_predicate'((_ < _)).
'$lgt_iso_spec_predicate'((_ >= _)).
'$lgt_iso_spec_predicate'((_ > _)).
'$lgt_iso_spec_predicate'((_ =:= _)).
'$lgt_iso_spec_predicate'((_ =\= _)).
% database
'$lgt_iso_spec_predicate'(clause(_, _)).
'$lgt_iso_spec_predicate'(current_predicate(_)).
'$lgt_iso_spec_predicate'(asserta(_)).
'$lgt_iso_spec_predicate'(assertz(_)).
'$lgt_iso_spec_predicate'(retract(_)).
'$lgt_iso_spec_predicate'(retractall(_)).
'$lgt_iso_spec_predicate'(abolish(_)).
% all solutions
'$lgt_iso_spec_predicate'(findall(_, _, _)).
'$lgt_iso_spec_predicate'(bagof(_, _, _)).
'$lgt_iso_spec_predicate'(setof(_, _, _)).
% stream selection and control
'$lgt_iso_spec_predicate'(current_input(_)).
'$lgt_iso_spec_predicate'(current_output(_)).
'$lgt_iso_spec_predicate'(set_input(_)).
'$lgt_iso_spec_predicate'(set_output(_)).
'$lgt_iso_spec_predicate'(open(_, _, _, _)).
'$lgt_iso_spec_predicate'(open(_, _, _)).
'$lgt_iso_spec_predicate'(close(_, _)).
'$lgt_iso_spec_predicate'(close(_)).
'$lgt_iso_spec_predicate'(flush_output(_)).
'$lgt_iso_spec_predicate'(flush_output).
'$lgt_iso_spec_predicate'(stream_property(_, _)).
'$lgt_iso_spec_predicate'(at_end_of_stream).
'$lgt_iso_spec_predicate'(at_end_of_stream(_)).
'$lgt_iso_spec_predicate'(set_stream_position(_, _)).
% character and byte input/output
'$lgt_iso_spec_predicate'(get_char(_, _)).
'$lgt_iso_spec_predicate'(get_char(_)).
'$lgt_iso_spec_predicate'(get_code(_, _)).
'$lgt_iso_spec_predicate'(get_code(_)).
'$lgt_iso_spec_predicate'(peek_char(_, _)).
'$lgt_iso_spec_predicate'(peek_char(_)).
'$lgt_iso_spec_predicate'(peek_code(_, _)).
'$lgt_iso_spec_predicate'(peek_code(_)).
'$lgt_iso_spec_predicate'(put_char(_, _)).
'$lgt_iso_spec_predicate'(put_char(_)).
'$lgt_iso_spec_predicate'(put_code(_, _)).
'$lgt_iso_spec_predicate'(put_code(_)).
'$lgt_iso_spec_predicate'(nl).
'$lgt_iso_spec_predicate'(nl(_)).
'$lgt_iso_spec_predicate'(get_byte(_, _)).
'$lgt_iso_spec_predicate'(get_byte(_)).
'$lgt_iso_spec_predicate'(peek_byte(_, _)).
'$lgt_iso_spec_predicate'(peek_byte(_)).
'$lgt_iso_spec_predicate'(put_byte(_, _)).
'$lgt_iso_spec_predicate'(put_byte(_)).
% term input/output
'$lgt_iso_spec_predicate'(read_term(_, _, _)).
'$lgt_iso_spec_predicate'(read_term(_, _)).
'$lgt_iso_spec_predicate'(read(_)).
'$lgt_iso_spec_predicate'(read(_, _)).
'$lgt_iso_spec_predicate'(write_term(_, _, _)).
'$lgt_iso_spec_predicate'(write_term(_, _)).
'$lgt_iso_spec_predicate'(write(_)).
'$lgt_iso_spec_predicate'(write(_, _)).
'$lgt_iso_spec_predicate'(writeq(_)).
'$lgt_iso_spec_predicate'(writeq(_, _)).
'$lgt_iso_spec_predicate'(write_canonical(_)).
'$lgt_iso_spec_predicate'(write_canonical(_, _)).
'$lgt_iso_spec_predicate'(op(_, _, _)).
'$lgt_iso_spec_predicate'(current_op(_, _, _)).
'$lgt_iso_spec_predicate'(char_conversion(_, _)).
'$lgt_iso_spec_predicate'(current_char_conversion(_, _)).
% logic and control
'$lgt_iso_spec_predicate'(\+ _).
'$lgt_iso_spec_predicate'(once(_)).
'$lgt_iso_spec_predicate'(repeat).
% atomic term processing
'$lgt_iso_spec_predicate'(atom_length(_, _)).
'$lgt_iso_spec_predicate'(atom_concat(_, _, _)).
'$lgt_iso_spec_predicate'(sub_atom(_, _, _, _, _)).
'$lgt_iso_spec_predicate'(atom_chars(_, _)).
'$lgt_iso_spec_predicate'(atom_codes(_, _)).
'$lgt_iso_spec_predicate'(char_code(_, _)).
'$lgt_iso_spec_predicate'(number_chars(_, _)).
'$lgt_iso_spec_predicate'(number_codes(_, _)).
% implementation defined hooks functions
'$lgt_iso_spec_predicate'(set_prolog_flag(_, _)).
'$lgt_iso_spec_predicate'(current_prolog_flag(_, _)).
'$lgt_iso_spec_predicate'(halt).
'$lgt_iso_spec_predicate'(halt(_)).
% sorting
'$lgt_iso_spec_predicate'(keysort(_, _)).
'$lgt_iso_spec_predicate'(sort(_, _)).
% the following predicates are not part of the ISO/IEC 13211-1 Prolog standard
% but can be found either on Core Revision standardization proposals or,
% more important, these predicates are or are becoming de facto standards
% term creation and decomposition
'$lgt_iso_spec_predicate'(numbervars(_, _, _)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% table of ISO Prolog specified arithmetic functions
%
% (used by the linter for portability checking)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_iso_spec_function'(?callable)
'$lgt_iso_spec_function'(pi).
'$lgt_iso_spec_function'('+'(_)).
'$lgt_iso_spec_function'('-'(_)).
'$lgt_iso_spec_function'('+'(_, _)).
'$lgt_iso_spec_function'('-'(_, _)).
'$lgt_iso_spec_function'('*'(_, _)).
'$lgt_iso_spec_function'('/'(_, _)).
'$lgt_iso_spec_function'('//'(_, _)).
'$lgt_iso_spec_function'(rem(_, _)).
'$lgt_iso_spec_function'(mod(_, _)).
'$lgt_iso_spec_function'(div(_, _)).
'$lgt_iso_spec_function'('/\\'(_, _)).
'$lgt_iso_spec_function'('\\/'(_, _)).
'$lgt_iso_spec_function'('\\'(_)).
'$lgt_iso_spec_function'('<<'(_, _)).
'$lgt_iso_spec_function'('>>'(_, _)).
'$lgt_iso_spec_function'(xor(_, _)).
'$lgt_iso_spec_function'('**'(_, _)).
'$lgt_iso_spec_function'('^'(_, _)).
'$lgt_iso_spec_function'(abs(_)).
'$lgt_iso_spec_function'(sign(_)).
'$lgt_iso_spec_function'(sqrt(_)).
'$lgt_iso_spec_function'(acos(_)).
'$lgt_iso_spec_function'(asin(_)).
'$lgt_iso_spec_function'(atan(_)).
'$lgt_iso_spec_function'(atan2(_, _)).
'$lgt_iso_spec_function'(cos(_)).
'$lgt_iso_spec_function'(sin(_)).
'$lgt_iso_spec_function'(tan(_)).
'$lgt_iso_spec_function'(exp(_)).
'$lgt_iso_spec_function'(log(_)).
'$lgt_iso_spec_function'(float(_)).
'$lgt_iso_spec_function'(ceiling(_)).
'$lgt_iso_spec_function'(floor(_)).
'$lgt_iso_spec_function'(round(_)).
'$lgt_iso_spec_function'(truncate(_)).
'$lgt_iso_spec_function'(float_fractional_part(_)).
'$lgt_iso_spec_function'(float_integer_part(_)).
'$lgt_iso_spec_function'(max(_, _)).
'$lgt_iso_spec_function'(min(_, _)).
% the following functions are not part of the ISO/IEC 13211-1 Prolog standard
% but can be found either on Core Revision standardization proposals or,
% more important, these functions are or are becoming de facto standards
'$lgt_iso_spec_function'(e).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% auxiliary predicates checking for float and integer arithmetic
% expressions (used for linter checks)
%
% these checks also recognize de facto standard arithmetic constants
% and functions
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_float_expression'(@term)
'$lgt_float_expression'(Exp) :-
var(Exp),
!,
fail.
'$lgt_float_expression'(Exp) :-
float(Exp),
!.
% basic arithmetic functions
'$lgt_float_expression'(Exp1 + Exp2) :-
( '$lgt_float_expression'(Exp1) ->
true
; '$lgt_float_expression'(Exp2)
).
'$lgt_float_expression'(Exp1 - Exp2) :-
( '$lgt_float_expression'(Exp1) ->
true
; '$lgt_float_expression'(Exp2)
).
'$lgt_float_expression'(Exp1 * Exp2) :-
( '$lgt_float_expression'(Exp1) ->
true
; '$lgt_float_expression'(Exp2)
).
'$lgt_float_expression'(_ / _).
'$lgt_float_expression'(_ ** _).
% other functions
'$lgt_float_expression'(abs(Exp)) :-
'$lgt_float_expression'(Exp).
'$lgt_float_expression'(sign(Exp)) :-
'$lgt_float_expression'(Exp).
'$lgt_float_expression'(max(Exp1, Exp2)) :-
( '$lgt_float_expression'(Exp1) ->
true
; '$lgt_float_expression'(Exp2)
).
'$lgt_float_expression'(min(Exp1, Exp2)) :-
( '$lgt_float_expression'(Exp1) ->
true
; '$lgt_float_expression'(Exp2)
).
'$lgt_float_expression'(float_integer_part(_)).
'$lgt_float_expression'(float_fractional_part(_)).
'$lgt_float_expression'(sqrt(_)).
'$lgt_float_expression'(exp(_)).
'$lgt_float_expression'(log(_)).
'$lgt_float_expression'(log(_, _)).
'$lgt_float_expression'(log10(_)).
% trignometric functions
'$lgt_float_expression'(acos(_)).
'$lgt_float_expression'(asin(_)).
'$lgt_float_expression'(atan(_)).
'$lgt_float_expression'(atan2(_, _)).
'$lgt_float_expression'(cos(_)).
'$lgt_float_expression'(sin(_)).
'$lgt_float_expression'(tan(_)).
% hyperbolic functions
'$lgt_float_expression'(sinh(_)).
'$lgt_float_expression'(cosh(_)).
'$lgt_float_expression'(tanh(_)).
'$lgt_float_expression'(asinh(_)).
'$lgt_float_expression'(acosh(_)).
'$lgt_float_expression'(atanh(_)).
% float arithmetic constants
'$lgt_float_expression'(e).
'$lgt_float_expression'(pi).
'$lgt_float_expression'(epsilon).
% '$lgt_integer_expression'(@term)
'$lgt_integer_expression'(Exp) :-
var(Exp),
!,
fail.
'$lgt_integer_expression'(Exp) :-
integer(Exp),
!.
% basic arithmetic functions
'$lgt_integer_expression'(Exp1 + Exp2) :-
'$lgt_integer_expression'(Exp1),
'$lgt_integer_expression'(Exp2).
'$lgt_integer_expression'(Exp1 - Exp2) :-
'$lgt_integer_expression'(Exp1),
'$lgt_integer_expression'(Exp2).
'$lgt_integer_expression'(Exp1 * Exp2) :-
'$lgt_integer_expression'(Exp1),
'$lgt_integer_expression'(Exp2).
'$lgt_integer_expression'(_ // _).
% other functions
'$lgt_integer_expression'(rem(_, _)).
'$lgt_integer_expression'(div(_, _)).
'$lgt_integer_expression'(mod(_, _)).
'$lgt_integer_expression'(gcd(_, _)).
'$lgt_integer_expression'(round(_)).
'$lgt_integer_expression'(truncate(_)).
'$lgt_integer_expression'(abs(Exp)) :-
'$lgt_integer_expression'(Exp).
'$lgt_integer_expression'(sign(Exp)) :-
'$lgt_integer_expression'(Exp).
'$lgt_integer_expression'(max(Exp1, Exp2)) :-
'$lgt_integer_expression'(Exp1),
'$lgt_integer_expression'(Exp2).
'$lgt_integer_expression'(min(Exp1, Exp2)) :-
'$lgt_integer_expression'(Exp1),
'$lgt_integer_expression'(Exp2).
% bitwise functions
'$lgt_integer_expression'(_ << _).
'$lgt_integer_expression'(_ >> _).
'$lgt_integer_expression'(_ /\ _).
'$lgt_integer_expression'(_ \/ _).
'$lgt_integer_expression'(xor(_, _)).
'$lgt_integer_expression'(\ _).
'$lgt_integer_expression'(lsb(_)).
'$lgt_integer_expression'(msb(_)).
'$lgt_integer_expression'(popcount(_)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% table of ISO Prolog operators
%
% (used by the linter for portability checking)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_iso_spec_operator'(?atom, ?atom, ?integer)
'$lgt_iso_spec_operator'((:-), xfx, 1200).
'$lgt_iso_spec_operator'((-->), xfx, 1200).
'$lgt_iso_spec_operator'((:-), fx, 1200).
'$lgt_iso_spec_operator'((?-), fx, 1200).
'$lgt_iso_spec_operator'((;), xfy, 1100).
'$lgt_iso_spec_operator'((->), xfy, 1050).
'$lgt_iso_spec_operator'((','), xfy, 1000).
'$lgt_iso_spec_operator'((\+), fy, 900).
'$lgt_iso_spec_operator'((=), xfx, 700).
'$lgt_iso_spec_operator'((\=), xfx, 700).
'$lgt_iso_spec_operator'((==), xfx, 700).
'$lgt_iso_spec_operator'((\==), xfx, 700).
'$lgt_iso_spec_operator'((@<), xfx, 700).
'$lgt_iso_spec_operator'((@=<), xfx, 700).
'$lgt_iso_spec_operator'((@>), xfx, 700).
'$lgt_iso_spec_operator'((@>=), xfx, 700).
'$lgt_iso_spec_operator'((=..), xfx, 700).
'$lgt_iso_spec_operator'((is), xfx, 700).
'$lgt_iso_spec_operator'((=:=), xfx, 700).
'$lgt_iso_spec_operator'((=\=), xfx, 700).
'$lgt_iso_spec_operator'((<), xfx, 700).
'$lgt_iso_spec_operator'((=<), xfx, 700).
'$lgt_iso_spec_operator'((>), xfx, 700).
'$lgt_iso_spec_operator'((>=), xfx, 700).
'$lgt_iso_spec_operator'((:), xfy, 600).
'$lgt_iso_spec_operator'((+), yfx, 500).
'$lgt_iso_spec_operator'((-), yfx, 500).
'$lgt_iso_spec_operator'((/\), yfx, 500).
'$lgt_iso_spec_operator'((\/), yfx, 500).
'$lgt_iso_spec_operator'((*), yfx, 400).
'$lgt_iso_spec_operator'((/), yfx, 400).
'$lgt_iso_spec_operator'((//), yfx, 400).
'$lgt_iso_spec_operator'((rem), yfx, 400).
'$lgt_iso_spec_operator'((mod), yfx, 400).
'$lgt_iso_spec_operator'((<<), yfx, 400).
'$lgt_iso_spec_operator'((>>), yfx, 400).
'$lgt_iso_spec_operator'((**), xfx, 200).
'$lgt_iso_spec_operator'((^), xfy, 200).
'$lgt_iso_spec_operator'((+), fy, 200).
'$lgt_iso_spec_operator'((-), fy, 200).
'$lgt_iso_spec_operator'((\), fy, 200).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% table of ISO Prolog specified flags
%
% (used for portability checking)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_iso_spec_flag'(?atom)
'$lgt_iso_spec_flag'(bounded).
'$lgt_iso_spec_flag'(max_integer).
'$lgt_iso_spec_flag'(min_integer).
'$lgt_iso_spec_flag'(integer_rounding_function).
'$lgt_iso_spec_flag'(max_arity).
'$lgt_iso_spec_flag'(char_conversion).
'$lgt_iso_spec_flag'(debug).
'$lgt_iso_spec_flag'(double_quotes).
'$lgt_iso_spec_flag'(unknown).
% the following flags are not part of the ISO/IEC 13211-1 Prolog standard
% but can be found either on the Core Revision standardization proposal or,
% more important, these flags are de facto standard
'$lgt_iso_spec_flag'(dialect).
'$lgt_iso_spec_flag'(version_data).
% '$lgt_iso_spec_flag_value'(+atom, @nonvar)
'$lgt_iso_spec_flag_value'(bounded, true) :- !.
'$lgt_iso_spec_flag_value'(bounded, false) :- !.
'$lgt_iso_spec_flag_value'(max_integer, Value) :-
integer(Value).
'$lgt_iso_spec_flag_value'(min_integer, Value) :-
integer(Value).
'$lgt_iso_spec_flag_value'(integer_rounding_function, toward_zero) :- !.
'$lgt_iso_spec_flag_value'(integer_rounding_function, down) :- !.
'$lgt_iso_spec_flag_value'(max_arity, Value) :-
integer(Value).
'$lgt_iso_spec_flag_value'(char_conversion, on) :- !.
'$lgt_iso_spec_flag_value'(char_conversion, off) :- !.
'$lgt_iso_spec_flag_value'(debug, on) :- !.
'$lgt_iso_spec_flag_value'(debug, off) :- !.
'$lgt_iso_spec_flag_value'(double_quotes, atom) :- !.
'$lgt_iso_spec_flag_value'(double_quotes, chars) :- !.
'$lgt_iso_spec_flag_value'(double_quotes, codes) :- !.
'$lgt_iso_spec_flag_value'(unknown, error) :- !.
'$lgt_iso_spec_flag_value'(unknown, warning) :- !.
'$lgt_iso_spec_flag_value'(unknown, fail) :- !.
'$lgt_iso_spec_flag_value'(dialect, Value) :-
atom(Value).
'$lgt_iso_spec_flag_value'(version_data, Value) :-
compound(Value).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% tables of ISO Prolog specified read and write term options
%
% (used for portability checking)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_iso_spec_open_stream_option'(@nonvar)
'$lgt_iso_spec_open_stream_option'(type(Type)) :-
( var(Type) ->
true
; Type == text ->
true
; Type == binary
).
'$lgt_iso_spec_open_stream_option'(reposition(Boolean)) :-
( var(Boolean) ->
true
; Boolean == true ->
true
; Boolean == false
).
'$lgt_iso_spec_open_stream_option'(alias(Alias)) :-
( var(Alias) ->
true
; atom(Alias)
).
'$lgt_iso_spec_open_stream_option'(eof_action(Action)) :-
( var(Action) ->
true
; Action == error ->
true
; Action == eof_code ->
true
; Action == reset
).
% '$lgt_iso_spec_read_term_option'(@nonvar)
'$lgt_iso_spec_read_term_option'(variables(_)).
'$lgt_iso_spec_read_term_option'(variable_names(_)).
'$lgt_iso_spec_read_term_option'(singletons(_)).
% '$lgt_iso_spec_write_term_option'(@nonvar)
'$lgt_iso_spec_write_term_option'(quoted(Boolean)) :-
( var(Boolean) ->
true
; Boolean == true ->
true
; Boolean == false
).
'$lgt_iso_spec_write_term_option'(ignore_ops(Boolean)) :-
( var(Boolean) ->
true
; Boolean == true ->
true
; Boolean == false
).
'$lgt_iso_spec_write_term_option'(numbervars(Boolean)) :-
( var(Boolean) ->
true
; Boolean == true ->
true
; Boolean == false
).
'$lgt_iso_spec_write_term_option'(variable_names(Pairs)) :-
'$lgt_is_list'(Pairs),
forall(
'$lgt_member'(Pair, Pairs),
(Pair = (Name = Variable), atom(Name), var(Variable))
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% table of ISO Prolog specified built-in database predicates
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_iso_database_predicate'(@callble)
'$lgt_iso_database_predicate'(abolish(_)).
'$lgt_iso_database_predicate'(asserta(_)).
'$lgt_iso_database_predicate'(assertz(_)).
'$lgt_iso_database_predicate'(clause(_, _)).
'$lgt_iso_database_predicate'(retract(_)).
'$lgt_iso_database_predicate'(retractall(_)).
'$lgt_iso_database_predicate'(current_predicate(_)).
'$lgt_iso_database_predicate'(predicate_property(_, _)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% table of Logtalk operators
%
% (used for portability checking)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_logtalk_spec_operator'(?atom, ?atom, ?integer)
% message sending operators
'$lgt_logtalk_spec_operator'((::), xfy, 600).
'$lgt_logtalk_spec_operator'((::), fy, 600).
% "super" call operator
'$lgt_logtalk_spec_operator'((^^), fy, 600).
% mode operators
'$lgt_logtalk_spec_operator'((?), fy, 200).
'$lgt_logtalk_spec_operator'((@), fy, 200).
'$lgt_logtalk_spec_operator'((++), fy, 200).
'$lgt_logtalk_spec_operator'((--), fy, 200).
% alias operator
'$lgt_logtalk_spec_operator'((as), xfx, 700).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Multi-threading support
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_init_object_message_queue'(+atom)
%
% creates a message queue for an object given its prefix
% (assume that any exception generated is due to the fact that the message
% queue already exists, which may happen when reloading threaded objects;
% there is no standard predicate for testing message queue existence)
'$lgt_init_object_message_queue'(ObjPrefix) :-
catch(message_queue_create(_, [alias(ObjPrefix)]), _, true).
% '$lgt_threaded_wait_synch_ctg'(+mutex_identifier, @term, @object_identifier)
%
% calls to the threaded_wait/1 predicate from synchronized category predicates
'$lgt_threaded_wait_synch_ctg'(Mutex, Msg, This) :-
'$lgt_current_object_'(This, Prefix, _, _, _, _, _, _, _, _, _),
mutex_unlock(Mutex),
'$lgt_threaded_wait'(Msg, Prefix),
mutex_lock(Mutex).
% '$lgt_threaded_wait_synch'(+mutex_identifier, @term, +entity_prefix)
%
% calls to the threaded_wait/1 predicate from synchronized object predicates
'$lgt_threaded_wait_synch'(Mutex, Msg, Prefix) :-
mutex_unlock(Mutex),
'$lgt_threaded_wait'(Msg, Prefix),
mutex_lock(Mutex).
% '$lgt_threaded_wait_ctg'(@term, @object_identifier)
'$lgt_threaded_wait_ctg'(Msg, This) :-
'$lgt_current_object_'(This, Prefix, _, _, _, _, _, _, _, _, _),
'$lgt_threaded_wait'(Msg, Prefix).
% '$lgt_threaded_wait'(@term, +entity_prefix)
'$lgt_threaded_wait'(Msg, Prefix) :-
var(Msg),
!,
thread_get_message(Prefix, '$lgt_notification'(Msg)).
'$lgt_threaded_wait'([], _) :-
!.
'$lgt_threaded_wait'([Msg| Msgs], Prefix) :-
!,
thread_get_message(Prefix, '$lgt_notification'(Msg)),
'$lgt_threaded_wait'(Msgs, Prefix).
'$lgt_threaded_wait'(Msg, Prefix) :-
thread_get_message(Prefix, '$lgt_notification'(Msg)).
% '$lgt_threaded_notify_ctg'(@term, @object_identifier)
'$lgt_threaded_notify_ctg'(Msg, This) :-
'$lgt_current_object_'(This, Prefix, _, _, _, _, _, _, _, _, _),
'$lgt_threaded_notify'(Msg, Prefix).
% '$lgt_threaded_notify'(@term, +entity_prefix)
'$lgt_threaded_notify'(Msg, Prefix) :-
var(Msg),
!,
thread_send_message(Prefix, '$lgt_notification'(Msg)).
'$lgt_threaded_notify'([], _) :-
!.
'$lgt_threaded_notify'([Msg| Msgs], Prefix) :-
!,
thread_send_message(Prefix, '$lgt_notification'(Msg)),
'$lgt_threaded_notify'(Msgs, Prefix).
'$lgt_threaded_notify'(Msg, Prefix) :-
thread_send_message(Prefix, '$lgt_notification'(Msg)).
% '$lgt_threaded_ignore'(@term, @callable, @execution_context)
%
% the thread is only created if the original goal is callable;
% this prevents programming errors going unnoticed
'$lgt_threaded_ignore'(Goal, TGoal, ExCtx) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_ignore(Goal), ExCtx)),
thread_create(catch(TGoal, _, true), _, [detached(true)]).
% '$lgt_threaded_call'(@term, @callable, @execution_context)
%
% the thread is only created if the original goal is callable; this prevents
% programming errors going unnoticed until we try to retrieve the first answer
'$lgt_threaded_call'(Goal, TGoal, ExCtx) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_call(Goal), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
thread_create('$lgt_mt_non_det_goal'(Queue, Goal, TGoal, This, Self, []), Id, []),
thread_send_message(Queue, '$lgt_thread_id'(call, Goal, This, Self, [], Id)).
% '$lgt_threaded_once'(@term, @callable, @execution_context)
%
% the thread is only created if the original goal is callable; this prevents
% programming errors going unnoticed until we try to retrieve the first answer
'$lgt_threaded_once'(Goal, TGoal, ExCtx) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_once(Goal), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
thread_create('$lgt_mt_det_goal'(Queue, Goal, TGoal, This, Self, []), Id, []),
thread_send_message(Queue, '$lgt_thread_id'(once, Goal, This, Self, [], Id)).
% '$lgt_threaded_call_tagged'(@term, @callable, @execution_context, -nonvar)
%
% the thread is only created if the original goal is callable and the tag is unbound;
% this prevents programming errors going unnoticed until we try to retrieve the first answer
'$lgt_threaded_call_tagged'(Goal, TGoal, ExCtx, Tag) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_call(Goal, Tag), ExCtx)),
'$lgt_check'(var, Tag, logtalk(threaded_call(Goal, Tag), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
'$lgt_new_threaded_tag'(Tag),
thread_create('$lgt_mt_non_det_goal'(Queue, Goal, TGoal, This, Self, Tag), Id, []),
thread_send_message(Queue, '$lgt_thread_id'(call, Goal, This, Self, Tag, Id)).
% '$lgt_threaded_once_tagged'(@term, @callable, @execution_context, -nonvar)
%
% the thread is only created if the original goal is callable and the tag is unbound;
% this programming errors going unnoticed until we try to retrieve the answer
'$lgt_threaded_once_tagged'(Goal, TGoal, ExCtx, Tag) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_once(Goal, Tag), ExCtx)),
'$lgt_check'(var, Tag, logtalk(threaded_once(Goal, Tag), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
'$lgt_new_threaded_tag'(Tag),
thread_create('$lgt_mt_det_goal'(Queue, Goal, TGoal, This, Self, Tag), Id, []),
thread_send_message(Queue, '$lgt_thread_id'(once, Goal, This, Self, Tag, Id)).
% '$lgt_mt_det_goal'(+message_queue_identifier, +callable, +callable, +object_identifier, +object_identifier, @nonvar)
%
% processes a deterministic message received by an object's message queue
'$lgt_mt_det_goal'(Queue, Goal, TGoal, This, Self, Tag) :-
thread_self(Id),
( catch(TGoal, Error, true) ->
( var(Error) ->
thread_send_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, success, Id))
; thread_send_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, Error, Id))
)
; thread_send_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, failure, Id))
).
% '$lgt_mt_non_det_goal'(+atom, +callable, +callable, +object_identifier, +object_identifier, @nonvar)
%
% processes a non-deterministic message received by an object's message queue
'$lgt_mt_non_det_goal'(Queue, Goal, TGoal, This, Self, Tag) :-
thread_self(Id),
( catch(TGoal, Error, true),
( var(Error) ->
thread_send_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, success, Id)),
thread_get_message(Message),
( Message == '$lgt_next' ->
% backtrack to the catch(Goal, ...) to try to find an alternative solution
fail
; % otherwise assume Message = '$lgt_exit' and terminate thread
true
)
; thread_send_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, Error, Id))
)
; % no (more) solutions
thread_send_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, failure, Id))
).
% '$lgt_threaded_peek'(+callable, @execution_context)
'$lgt_threaded_peek'(Goal, ExCtx) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_peek(Goal), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
( % first check if there is a thread running for proving the goal before proceeding
thread_peek_message(Queue, '$lgt_thread_id'(_, Goal, This, Self, [], Id)) ->
% answering thread exists; go ahead and peek a solution
thread_peek_message(Queue, '$lgt_reply'(Goal, This, Self, [], _, Id))
; % answering thread don't exist; generate an exception
throw(error(existence_error(thread, This), logtalk(threaded_peek(Goal), ExCtx)))
).
% '$lgt_threaded_peek_tagged'(+callable, @execution_context, @nonvar)
'$lgt_threaded_peek_tagged'(Goal, ExCtx, Tag) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_peek(Goal, Tag), ExCtx)),
'$lgt_check'(nonvar, Tag, logtalk(threaded_peek(Goal, Tag), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
( % first check if there is a thread running for proving the goal before proceeding
thread_peek_message(Queue, '$lgt_thread_id'(_, Goal, This, Self, Tag, Id)) ->
% answering thread exists; go ahead and peek a solution
thread_peek_message(Queue, '$lgt_reply'(Goal, This, Self, Tag, _, Id))
; % answering thread don't exist; generate an exception
throw(error(existence_error(thread, This), logtalk(threaded_peek(Goal, Tag), ExCtx)))
).
% '$lgt_threaded_cancel_tagged'(@nonvar, @execution_context)
'$lgt_threaded_cancel_tagged'(Tag, ExCtx) :-
'$lgt_check'(nonvar, Tag, logtalk(threaded_cancel(Tag), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
( thread_peek_message(Queue, '$lgt_thread_id'(_, _, This, Self, Tag, Id)) ->
% answering thread exists; go ahead and cancel it
thread_get_message(Queue, '$lgt_thread_id'(_, _, This, Self, Tag, Id)),
% the thread may be suspended waiting for a request for an alternative proof; tell it to exit
thread_send_message(Id, '$lgt_exit'),
% but the thread may also be busy computing a solution; cancel it
catch(thread_signal(Id, throw('$lgt_aborted')), _, true),
thread_join(Id, _),
% delete any thread reply that is pending retrievel
forall(
thread_peek_message(Queue, '$lgt_reply'(_, This, Self, Tag, _, Id)),
thread_get_message(Queue, '$lgt_reply'(_, This, Self, Tag, _, Id))
)
; % assume thread already canceled
true
).
% '$lgt_threaded_exit'(+callable, @execution_context)
'$lgt_threaded_exit'(Goal, ExCtx) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_exit(Goal), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
( % first check if there is a thread running for proving the goal before proceeding
thread_peek_message(Queue, '$lgt_thread_id'(Type, Goal, This, Self, [], Id)) ->
% answering thread exists; go ahead and retrieve the solution(s)
thread_get_message(Queue, '$lgt_thread_id'(Type, Goal, This, Self, [], Id)),
( Type == (once) ->
setup_call_cleanup(
true,
'$lgt_mt_det_reply'(Queue, Goal, This, Self, [], Id),
thread_join(Id, _)
)
; setup_call_cleanup(
true,
'$lgt_mt_non_det_reply'(Queue, Goal, This, Self, [], Id),
(( thread_property(Id, status(running)) ->
% thread still running, suspended waiting for a request to an alternative proof; tell it to exit
thread_send_message(Id, '$lgt_exit')
; true
),
thread_join(Id, _))
)
)
; % answering thread don't exist; generate an exception (failing is not an option as it could simply mean goal failure)
throw(error(existence_error(thread, This), logtalk(threaded_exit(Goal), ExCtx)))
).
% '$lgt_threaded_exit_tagged'(+callable, @execution_context, @nonvar)
'$lgt_threaded_exit_tagged'(Goal, ExCtx, Tag) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_exit(Goal, Tag), ExCtx)),
'$lgt_check'(nonvar, Tag, logtalk(threaded_exit(Goal, Tag), ExCtx)),
'$lgt_execution_context'(ExCtx, _, _, This, Self, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
( % first check if there is a thread running for proving the goal before proceeding
thread_peek_message(Queue, '$lgt_thread_id'(Type, Goal, This, Self, Tag, Id)) ->
% answering thread exists; go ahead and retrieve the solution(s)
thread_get_message(Queue, '$lgt_thread_id'(Type, Goal, This, Self, Tag, Id)),
( Type == (once) ->
setup_call_cleanup(
true,
'$lgt_mt_det_reply'(Queue, Goal, This, Self, Tag, Id),
thread_join(Id, _)
)
; setup_call_cleanup(
true,
'$lgt_mt_non_det_reply'(Queue, Goal, This, Self, Tag, Id),
(( thread_property(Id, status(running)) ->
% thread still running, suspended waiting for a request to an alternative proof; tell it to exit
thread_send_message(Id, '$lgt_exit')
; true
),
thread_join(Id, _))
)
)
; % answering thread don't exist; generate an exception (failing is not an option as it could simply mean goal failure)
throw(error(existence_error(thread, This), logtalk(threaded_exit(Goal, Tag), ExCtx)))
).
% return the solution found
'$lgt_mt_det_reply'(Queue, Goal, This, Self, Tag, Id) :-
thread_get_message(Queue, '$lgt_reply'(Reply, This, Self, Tag, Result, Id)),
( Result == success ->
Goal = Reply
; Result == failure ->
fail
; throw(Result)
).
% return current solution; on backtracking, ask working thread for and get from it the next solution
'$lgt_mt_non_det_reply'(Queue, Goal, This, Self, Tag, Id) :-
thread_get_message(Queue, '$lgt_reply'(Reply, This, Self, Tag, Result, Id)),
( Result == success ->
Goal = Reply
; Result == failure ->
!,
fail
; throw(Result)
).
'$lgt_mt_non_det_reply'(Queue, Goal, This, Self, Tag, Id) :-
catch(thread_send_message(Id, '$lgt_next'), _, fail),
'$lgt_mt_non_det_reply'(Queue, Goal, This, Self, Tag, Id).
% '$lgt_threaded_engine_create'(@term, @term, @callable, +object_identifier, ?nonvar)
%
% the engine thread is only created if the original goal is callable; this prevents
% programming errors going unnoticed until we try to retrieve the first answer
'$lgt_threaded_engine_create'(AnswerTemplate, Goal, TGoal, ExCtx, Engine) :-
'$lgt_check'(qualified_callable, Goal, logtalk(threaded_engine_create(AnswerTemplate, Goal, Engine), ExCtx)),
with_mutex(
'$lgt_engines',
'$lgt_threaded_engine_create_protected'(AnswerTemplate, Goal, TGoal, ExCtx, Engine)
).
'$lgt_threaded_engine_create_protected'(AnswerTemplate, Goal, TGoal, ExCtx, Engine) :-
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _),
( var(Engine) ->
'$lgt_new_threaded_engine_tag'(Engine)
; '$lgt_current_engine_'(This, Engine, _, _) ->
throw(error(permission_error(create, engine, Engine), logtalk(threaded_engine_create(AnswerTemplate, Goal, Engine), ExCtx)))
; true
),
'$lgt_current_object_'(This, ThisQueue, _, _, _, _, _, _, _, _, _),
message_queue_create(TermQueue),
thread_create('$lgt_mt_engine_goal'(ThisQueue, TermQueue, AnswerTemplate, TGoal, Engine, Id), Id, []),
assertz('$lgt_current_engine_'(This, Engine, TermQueue, Id)).
% compute a solution for the engine goal and return it; note that the thread
% always terminates with a status of "true" when an exception occurs or there
% aren't any more solutions for the engine goal
%
% we use the object queue to store a '$lgt_engine_term_queue'/3 term with the
% engine name and the engine term queue to workaround random timing issues when
% accessing the '$lgt_current_engine_'/4 dynamic predicate that can result in
% unexpected errors
'$lgt_mt_engine_goal'(ThisQueue, TermQueue, Answer, Goal, Engine, Id) :-
thread_send_message(ThisQueue, '$lgt_engine_term_queue'(Engine, TermQueue, Id)),
( setup_call_cleanup(true, catch(Goal, Error, true), Deterministic = true),
( var(Error) ->
( var(Deterministic) ->
thread_send_message(ThisQueue, '$lgt_answer'(Engine, Id, Answer, success)),
thread_get_message(Message),
% if Message = '$lgt_next', backtrack to try to find an alternative solution
Message == '$lgt_aborted'
; % no (more) solutions after this one
thread_send_message(ThisQueue, '$lgt_answer'(Engine, Id, Answer, final))
)
; Error == '$lgt_aborted' ->
% we are destroying the engine
true
; % engine goal error
thread_send_message(ThisQueue, '$lgt_answer'(Engine, Id, _, error(Error)))
)
; % no (more) solutions
thread_send_message(ThisQueue, '$lgt_answer'(Engine, Id, _, failure))
).
% '$lgt_current_engine'(@object_identifier, ?nonvar)
%
% we cannot compile threaded_engine/1 calls into '$lgt_current_engine_'/2 calls
% as the last two arguments would cause problems with bagof/3 and setof/3 calls
'$lgt_current_engine'(This, Engine) :-
'$lgt_current_engine_'(This, Engine, _, _).
% '$lgt_threaded_engine_next'(@nonvar, ?term, @execution_context)
%
% blocks until an answer (either an engine goal solution or a solution
% posted by a call to threaded_engine_yield/1) becomes available
'$lgt_threaded_engine_next'(Engine, Answer, ExCtx) :-
( var(Engine) ->
throw(error(instantiation_error, logtalk(threaded_engine_next(Engine, Answer), ExCtx)))
; '$lgt_execution_context'(ExCtx, _, _, This, _, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
% first check if the engine is running
'$lgt_current_engine_'(This, Engine, _, Id) ->
% engine exists; go ahead and retrieve an answer
'$lgt_mt_engine_reply'(Queue, Answer, Engine, Id, ExCtx)
; % engine does not exist
throw(error(existence_error(engine, Engine), logtalk(threaded_engine_next(Engine, Answer), ExCtx)))
).
% return current answer and start computing the next one
% if the engine goal succeeded non-deterministically
%
% after all solutions are consumed, or in case of error,
% ensure that the all next calls will fail
'$lgt_mt_engine_reply'(Queue, Answer, Engine, Id, ExCtx) :-
thread_get_message(Queue, '$lgt_answer'(Engine, Id, Reply, Result)),
( Result == success ->
thread_send_message(Id, '$lgt_next'),
Answer = Reply
; Result == final ->
thread_send_message(Queue, '$lgt_answer'(Engine, Id, '$lgt_done'(final), failure)),
Answer = Reply
; Result == failure ->
thread_send_message(Queue, '$lgt_answer'(Engine, Id, '$lgt_done'(failure), failure)),
fail
; Result = error(Error),
thread_send_message(Queue, '$lgt_answer'(Engine, Id, '$lgt_done'(error), failure)),
throw(error(Error, logtalk(threaded_engine_next(Engine,Answer),ExCtx)))
).
% '$lgt_threaded_engine_next_reified'(@nonvar, ?term, @execution_context)
%
% blocks until an answer (either an engine goal solution or a solution
% posted by a call to threaded_engine_yield/1) becomes available
'$lgt_threaded_engine_next_reified'(Engine, Answer, ExCtx) :-
( var(Engine) ->
throw(error(instantiation_error, logtalk(threaded_engine_next_reified(Engine, Answer), ExCtx)))
; '$lgt_execution_context'(ExCtx, _, _, This, _, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
% first check if the engine is running
'$lgt_current_engine_'(This, Engine, _, Id) ->
% engine exists; go ahead and retrieve an answer
'$lgt_mt_engine_reply_reified'(Queue, Answer, Engine, Id)
; % engine does not exist
throw(error(existence_error(engine, Engine), logtalk(threaded_engine_next_reified(Engine, Answer), ExCtx)))
).
% return current answer and start computing the next one
% if the engine goal succeeded non-deterministically
%
% after all solutions are consumed, or in case of error,
% ensure that the all next calls will fail
'$lgt_mt_engine_reply_reified'(Queue, Answer, Engine, Id) :-
thread_get_message(Queue, '$lgt_answer'(Engine, Id, Reply, Result)),
( Result == success ->
thread_send_message(Id, '$lgt_next'),
Answer = the(Reply)
; Result == final ->
thread_send_message(Queue, '$lgt_answer'(Engine, Id, '$lgt_done'(final), failure)),
Answer = the(Reply)
; Result == failure ->
thread_send_message(Queue, '$lgt_answer'(Engine, Id, '$lgt_done'(failure), failure)),
Answer = no
; Result = error(Error),
thread_send_message(Queue, '$lgt_answer'(Engine, Id, '$lgt_done'(error), failure)),
Answer = exception(Error)
).
% '$lgt_threaded_engine_self'(@object_identifier, ?nonvar)
%
% fails if not called from within an engine
'$lgt_threaded_engine_self'(This, Engine) :-
thread_self(Id),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
thread_peek_message(Queue, '$lgt_engine_term_queue'(Engine0, _, Id)),
!,
Engine = Engine0.
% '$lgt_threaded_engine_yield'(@term, @object_identifier)
%
% fails if not called from within an engine;
% blocks until the returned answer is consumed
'$lgt_threaded_engine_yield'(Answer, This) :-
thread_self(Id),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
thread_peek_message(Queue, '$lgt_engine_term_queue'(Engine, _, Id)),
thread_send_message(Queue, '$lgt_answer'(Engine, Id, Answer, success)),
thread_get_message(_).
% '$lgt_threaded_engine_post'(@nonvar, @term, @execution_context)
'$lgt_threaded_engine_post'(Engine, Term, ExCtx) :-
'$lgt_execution_context'(ExCtx, _, _, This, _, _, _),
( var(Engine) ->
throw(error(instantiation_error, logtalk(threaded_engine_post(Engine, Term), ExCtx)))
; % first check if the engine is running
'$lgt_current_engine_'(This, Engine, TermQueue, _) ->
% engine exists; go ahead and post the message in its mailbox
thread_send_message(TermQueue, Term)
; % engine does not exist
throw(error(existence_error(engine, Engine), logtalk(threaded_engine_post(Engine, Term), ExCtx)))
).
% '$lgt_threaded_engine_fetch'(?term, @object_identifier)
%
% fails if not called from within an engine or if we are
% destroying a running engine
'$lgt_threaded_engine_fetch'(Term, This) :-
thread_self(Id),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
( % check if calling from within an engine
thread_peek_message(Queue, '$lgt_engine_term_queue'(_, TermQueue, Id)) ->
% engine exists; go ahead and retrieve a message from its mailbox
thread_get_message(TermQueue, Term),
Term \== '$lgt_aborted'
; % engine does not exist
fail
).
% '$lgt_threaded_engine_destroy'(@nonvar, @execution_context)
%
% when the engine thread is still running, we first put a throw/1 goal in the
% thread signal queue and then send messages to both the thread queue and the
% engine term queue to resume the engine goal if suspended waiting for either
% a request for the next solution or a term to be processed
'$lgt_threaded_engine_destroy'(Engine, ExCtx) :-
with_mutex(
'$lgt_engines',
'$lgt_threaded_engine_destroy_protected'(Engine, ExCtx)
).
'$lgt_threaded_engine_destroy_protected'(Engine, ExCtx) :-
( var(Engine) ->
throw(error(instantiation_error, logtalk(threaded_engine_destroy(Engine), ExCtx)))
; '$lgt_execution_context'(ExCtx, _, _, This, _, _, _),
'$lgt_current_object_'(This, Queue, _, _, _, _, _, _, _, _, _),
retract('$lgt_current_engine_'(This, Engine, TermQueue, Id)) ->
( thread_property(Id, status(running)) ->
% the engine thread may be suspended waiting for a client request to
% compute the next solution; send it a '$lgt_aborted' term to prevent
% further requests for backtracking into the next solution; note that
% the engine thread and therefore its queue may no longer exist
catch(thread_send_message(Id, '$lgt_aborted'), _, true),
% send the '$lgt_aborted' term to the engine term queue to make any further
% threaded_engine_fetch/1 calls fail; this queue is explicitly created and
% destroyed and thus we can be sure it exists
thread_send_message(TermQueue, '$lgt_aborted')
; true
),
% ensure that thread is terminated
catch(thread_signal(Id, throw('$lgt_aborted')), _, true),
thread_join(Id, _),
message_queue_destroy(TermQueue),
% remove any non-consumed answer
( thread_peek_message(Queue, '$lgt_answer'(Engine, Id, _, _)) ->
thread_get_message(Queue, '$lgt_answer'(Engine, Id, _, _))
; true
),
% remove the answer that ensures threaded_engine_next/2 and threaded_engine_next_reified/2
% return failures after consuming all solutions if present
( thread_peek_message(Queue, '$lgt_answer'(Engine, Id, _, failure)) ->
thread_get_message(Queue, '$lgt_answer'(Engine, Id, _, failure))
; true
),
% remove the cache entry for the engine term queue handle
( thread_peek_message(Queue, '$lgt_engine_term_queue'(Engine, _, Id)) ->
thread_get_message(Queue, '$lgt_engine_term_queue'(Engine, _, Id))
; true
)
; % engine doesn't exist
throw(error(existence_error(engine, Engine), logtalk(threaded_engine_destroy(Engine), ExCtx)))
).
% '$lgt_threaded_and'(-var, +callable, +list)
%
% implements the threaded/1 built-in predicate when the argument is a conjunction
%
% each call uses a dedicated message queue that is destroyed after joining the
% threads that are created to run the individual goals
'$lgt_threaded_and'(Queue, MTGoals, Results) :-
message_queue_create(Queue),
call(MTGoals),
'$lgt_mt_threaded_and_exit'(Queue, Results).
% '$lgt_threaded_or'(-var, +callable, +list)
%
% implements the threaded/1 built-in predicate when the argument is a disjunction
%
% each call uses a dedicated message queue that is destroyed after joining the
% threads that are created to run the individual goals
'$lgt_threaded_or'(Queue, MTGoals, Results) :-
message_queue_create(Queue),
call(MTGoals),
'$lgt_mt_threaded_or_exit'(Queue, Results).
% '$lgt_threaded_goal'(+callable, -list(var), +message_queue_identifier, --thread_identifier)
%
% implements the call to an individual goal by the threaded/1 built-in predicate
%
% the at_exit/1 is used to ensure that the individual thread result is sent to
% the dedicated message queue of the parent threaded/1 predicate call
'$lgt_threaded_goal'(TGoal, TVars, Queue, Id) :-
term_variables(TGoal, TVars),
thread_create(
'$lgt_mt_threaded_call'(TGoal, TVars, Queue, Id),
Id,
[at_exit('$lgt_mt_exit_handler'(Id, Queue))]
).
% '$lgt_mt_threaded_call'(+callable, +list(var), +message_queue_identifier)
%
% proves an individual goal from a threaded/1 predicate call and sends the
% result back to the message queue associated to the call; assuming that
% the thread is not interrupted, its final status is set to "true"; if the
% thread is interrupted before sending its result, its at_exit/1 option goal
% ensures that a result is still sent to the parent threaded/1 predicate call
% dedicated message queue
'$lgt_mt_threaded_call'(TGoal, TVars, Queue, Id) :-
( call(TGoal) ->
thread_send_message(Queue, '$lgt_result'(Id, true(TVars)))
; thread_send_message(Queue, '$lgt_result'(Id, false))
).
% '$lgt_mt_exit_handler'(@thread_identifier, +message_queue_identifier)
%
% exit handler for threaded/1 individual thread calls; an error generated
% by the thread_send_message/2 call is interpreted as meaning that the
% master/parent thread queue no longer exists leading to the detaching of
% the worker thread
'$lgt_mt_exit_handler'(Id, Queue) :-
( thread_property(Id, status(exception(Error))) ->
catch(thread_send_message(Queue, '$lgt_result'(Id, exception(Error))), _, thread_detach(Id))
; true
).
% '$lgt_mt_threaded_and_exit'(+message_queue_identifier, +list)
%
% retrieves the result of proving a conjunction of goals using a threaded/1 predicate call
% by collecting the individual thread results posted to the master thread message queue
% until all individual goals succeeds or one them fails or throws an exception
'$lgt_mt_threaded_and_exit'(Queue, Results) :-
thread_get_message(Queue, '$lgt_result'(Id, Result)),
'$lgt_mt_threaded_and_exit'(Result, Id, Queue, Results).
'$lgt_mt_threaded_and_exit'(exception(Error), Id, Queue, Results) :-
'$lgt_mt_threaded_and_record_result'(Results, Id, exception(Error)),
'$lgt_mt_threaded_call_cancel'(Queue, Results),
throw(Error).
'$lgt_mt_threaded_and_exit'(true(TVars), Id, Queue, Results) :-
( '$lgt_mt_threaded_and_add_result'(Results, Id, TVars, Continue) ->
( Continue == false ->
% all thread goals succeeded
'$lgt_mt_threaded_call_join'(Results, Queue)
; % some thread goal results are still pending
'$lgt_mt_threaded_and_exit'(Queue, Results)
)
; % adding a successful result can fail if the individual thread goals
% are not independent (i.e. they share variables with the same or
% partially the same role leading to unification failures)
'$lgt_mt_threaded_and_exit'(false, Id, Queue, Results)
).
'$lgt_mt_threaded_and_exit'(false, Id, Queue, Results) :-
'$lgt_mt_threaded_and_record_result'(Results, Id, false),
'$lgt_mt_threaded_call_cancel'(Queue, Results),
fail.
% '$lgt_mt_threaded_and_add_result'(+list, +thread_identifier, +list, -atom)
%
% adds the result of proving a goal and checks if all other goals have succeeded
'$lgt_mt_threaded_and_add_result'([id(Id, TVars, true)| Results], Id, TVars, Continue) :-
!,
( var(Continue) ->
% we still don't know if there are any pending results
'$lgt_mt_threaded_continue'(Results, Continue)
; true
).
'$lgt_mt_threaded_and_add_result'([id(_, _, Done)| Results], Id, TVars, Continue) :-
( var(Done) ->
% we found a thread whose result is still pending
Continue = true
; % otherwise continue examining the remaining thread results
true
),
'$lgt_mt_threaded_and_add_result'(Results, Id, TVars, Continue).
% '$lgt_mt_threaded_and_record_result'(+list, +thread_identifier, +callable)
%
% records a thread goal result
'$lgt_mt_threaded_and_record_result'([id(Id, _, Result)| _], Id, Result) :-
!.
'$lgt_mt_threaded_and_record_result'([_| Results], Id, Result) :-
'$lgt_mt_threaded_and_record_result'(Results, Id, Result).
% '$lgt_mt_threaded_or_exit'(+list)
%
% retrieves the result of proving a disjunction of goals using a threaded/1 predicate
% call by collecting the individual thread results posted to the call message queue
% until one of the individual goals succeeds or all goals fail or throw an exception
'$lgt_mt_threaded_or_exit'(Queue, Results) :-
thread_get_message(Queue, '$lgt_result'(Id, Result)),
'$lgt_mt_threaded_or_exit'(Result, Id, Queue, Results).
'$lgt_mt_threaded_or_exit'(exception(Error), Id, Queue, Results) :-
'$lgt_mt_threaded_or_record_exception'(Results, Id, exception(Error), Continue),
( Continue == true ->
% some thread goal results are still pending
'$lgt_mt_threaded_or_exit'(Queue, Results)
; % no thread goal succeeded and at least one thread resulted in an exception
'$lgt_mt_threaded_call_join'(Results, Queue),
throw(Error)
).
'$lgt_mt_threaded_or_exit'(true(TVars), Id, Queue, Results) :-
'$lgt_mt_threaded_or_exit_unify'(Results, Id, TVars),
'$lgt_mt_threaded_call_cancel'(Queue, Results).
'$lgt_mt_threaded_or_exit'(false, Id, Queue, Results) :-
'$lgt_mt_threaded_or_record_failure'(Results, Id, Continue),
( Continue == true ->
% some thread goal results are still pending
'$lgt_mt_threaded_or_exit'(Queue, Results)
; % all goals terminated
'$lgt_mt_threaded_call_join'(Results, Queue),
( '$lgt_member'(id(_, _, exception(Error)), Results) ->
throw(Error)
; % all threads failed
fail
)
).
% unifies the successful thread goal result with the original call
'$lgt_mt_threaded_or_exit_unify'([id(Id, TVars, true)| _], Id, TVars) :-
!.
'$lgt_mt_threaded_or_exit_unify'([_| Results], Id, TVars) :-
'$lgt_mt_threaded_or_exit_unify'(Results, Id, TVars).
% '$lgt_mt_threaded_or_record_exception'(+list, +thread_identifier, @nonvar, -atom)
%
% records a thread goal exception and checks if all other thread goals have
% failed or thrown exceptions
'$lgt_mt_threaded_or_record_exception'([id(Id, _, Result)| Results], Id, Exception, Continue) :-
!,
( var(Result) ->
Result = Exception
; % assume thread cancel exception; ignore it as the thread terminated
% before receiving the signal with its result already recorded
true
),
( var(Continue) ->
% we still don't know if there are any pending results
'$lgt_mt_threaded_continue'(Results, Continue)
; true
).
'$lgt_mt_threaded_or_record_exception'([id(_, _, Done)| Results], Id, Exception, Continue) :-
( var(Done) ->
% we found a thread whose result is still pending
Continue = true
; % otherwise continue examining the remaining thread results
true
),
'$lgt_mt_threaded_or_record_exception'(Results, Id, Exception, Continue).
% '$lgt_mt_threaded_or_record_failure'(+list, +thread_identifier, -atom)
%
% records a thread goal failure and checks if all other thread goals have failed
'$lgt_mt_threaded_or_record_failure'([id(Id, _, false)| Results], Id, Continue) :-
!,
( var(Continue) ->
% we still don't know if there are any pending results
'$lgt_mt_threaded_continue'(Results, Continue)
; true
).
'$lgt_mt_threaded_or_record_failure'([id(_, _, Done)| Results], Id, Continue) :-
( var(Done) ->
% we found a thread whose result is still pending
Continue = true
; % otherwise continue examining the remaining thread results
true
),
'$lgt_mt_threaded_or_record_failure'(Results, Id, Continue).
% '$lgt_mt_threaded_continue'(+list, -atom)
%
% checks if there are results still pending for a threaded/1 call
'$lgt_mt_threaded_continue'([], false).
'$lgt_mt_threaded_continue'([id(_, _, Done)| Results], Continue) :-
( var(Done) ->
% we found a thread whose result is still pending
Continue = true
; % otherwise continue looking for a thread with a still pending result
'$lgt_mt_threaded_continue'(Results, Continue)
).
% '$lgt_mt_threaded_call_cancel'(+message_queue_identifier, +list)
%
% aborts a threaded call by aborting and joining all individual threads;
% we must use catch/3 as some threads may already be terminated
'$lgt_mt_threaded_call_cancel'(Queue, Results) :-
'$lgt_mt_threaded_call_abort'(Results, Queue),
'$lgt_mt_threaded_call_join'(Results, Queue).
% '$lgt_mt_threaded_call_abort'(+list)
%
% signals individual threads to abort if their result is not yet registered;
% we must use catch/3 as some threads may no longer exist
'$lgt_mt_threaded_call_abort'([], _).
'$lgt_mt_threaded_call_abort'([id(Id, _, Result)| Ids], Queue) :-
( var(Result) ->
catch(thread_signal(Id, throw('$lgt_aborted')), _, true)
; true
),
'$lgt_mt_threaded_call_abort'(Ids, Queue).
% '$lgt_mt_threaded_call_join'(+list, +message_queue_identifier)
%
% joins all individual threads; we must use catch/3 as some threads may no longer exist
'$lgt_mt_threaded_call_join'([], Queue) :-
message_queue_destroy(Queue).
'$lgt_mt_threaded_call_join'([id(Id, _, _)| Results], Queue) :-
catch(thread_join(Id, _), _, true),
'$lgt_mt_threaded_call_join'(Results, Queue).
% '$lgt_new_threaded_tag'(-integer)
%
% generates a new multi-threading tag; used in the built-in asynchronous
% multi-threading predicates
'$lgt_new_threaded_tag'(New) :-
with_mutex(
'$lgt_threaded_tag',
( retract('$lgt_threaded_tag_counter_'(Old)),
New is Old + 1,
asserta('$lgt_threaded_tag_counter_'(New))
)
).
% '$lgt_new_threaded_engine_tag'(-integer)
%
% generates a new threading engine tag (already protected by the '$lgt_engines' mutex)
'$lgt_new_threaded_engine_tag'(New) :-
retract('$lgt_threaded_engine_tag_counter_'(Old)), !,
New is Old + 1,
asserta('$lgt_threaded_engine_tag_counter_'(New)).
% '$lgt_create_mutexes'(+list(mutex_identifier))
%
% creates entity mutexes (called when loading an entity); we may
% be reloading an entity and the mutex may be already created
'$lgt_create_mutexes'([]).
'$lgt_create_mutexes'([Mutex| Mutexes]) :-
( mutex_property(_, alias(Mutex)) ->
true
; mutex_create(_, [alias(Mutex)])
),
'$lgt_create_mutexes'(Mutexes).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% static binding supporting predicates
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_send_to_obj_static_binding'(@object_identifier, @callable, @object_identifier, -callable)
%
% static binding is only used for the (::)/2 control construct when the object receiving the
% message is static and the support for complementing categories is disallowed (unfortunately,
% allowing hot patching of an object would easily lead to inconsistencies as there isn't any
% portable solution for updating in-place the definition of patched object predicates that
% were already directly called due to the previous use of static binding)
'$lgt_send_to_obj_static_binding'(Obj, Pred, Call, Ctx) :-
'$lgt_comp_ctx'(Ctx, _, _, _, _, This, _, _, _, _, CallerExCtx, _, _, _, _),
( '$lgt_send_to_obj_static_binding_'(Obj, Pred, CallerExCtx, Call) ->
true
; '$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, ObjFlags),
ObjFlags /\ 512 =\= 512,
% object is not compiled in debug mode
ObjFlags /\ 2 =:= 0,
% object is static
ObjFlags /\ 64 =\= 64,
% complementing categories flag not set to "allow"
'$lgt_term_template'(Pred, GPred),
call(Dcl, GPred, p(p(p)), Meta, PredFlags, _, DclCtn), !,
% get the execution context for meta-calls
'$lgt_goal_meta_call_context'(Meta, GCallerExCtx, GThis, GMetaCallCtx),
'$lgt_term_template'(Obj, GObj),
'$lgt_execution_context'(GExCtx, _, GThis, GObj, GObj, GMetaCallCtx, []),
call(Def, GPred, GExCtx, GCall, _, DefCtn), !,
( PredFlags /\ 2 =:= 0 ->
% Type == static
true
; % Type == (dynamic)
GObj = DclCtn ->
% local declaration
true
; GObj = DefCtn
% local definition
),
( GObj \= DefCtn ->
% inherited definition; complementing categories
% flag must also not be set to "restrict"
ObjFlags /\ 32 =\= 32
; % local definition
true
),
% predicate definition found; use it only if it's safe
'$lgt_static_binding_safe_paths'(GObj, DclCtn, DefCtn),
( Meta == no ->
% cache only normal predicates
assertz('$lgt_send_to_obj_static_binding_'(GObj, GPred, GCallerExCtx, GCall)),
Obj = GObj, Pred = GPred, This = GThis, CallerExCtx = GCallerExCtx, Call = GCall
; % meta-predicates cannot be cached as they require translation of
% the meta-arguments, which must succeed to allow static binding
% (don't require the predicate and the meta-predicate template to
% share the name as we may be using a predicate alias)
Meta =.. [_| MArgs],
Pred =.. [PredFunctor| Args],
'$lgt_compile_static_binding_meta_arguments'(Args, MArgs, _, Ctx, TArgs),
TPred =.. [PredFunctor| TArgs],
Obj = GObj, TPred = GPred, This = GThis, CallerExCtx = GCallerExCtx, Call = GCall
)
).
'$lgt_compile_static_binding_meta_arguments'([], [], _, _, []).
'$lgt_compile_static_binding_meta_arguments'([Arg| Args], [MArg| MArgs], Caller, Ctx, [TArg| TArgs]) :-
'$lgt_compile_static_binding_meta_argument'(MArg, Arg, Caller, Ctx, TArg),
'$lgt_compile_static_binding_meta_arguments'(Args, MArgs, Caller, Ctx, TArgs).
'$lgt_compile_static_binding_meta_argument'((*), Arg, _, _, Arg) :-
!.
'$lgt_compile_static_binding_meta_argument'(N, Closure, _, Ctx, {UserClosure}) :-
integer(N),
% goal or closure
nonvar(Closure),
( Closure = Obj::UserClosure, Obj == user
; Closure = {UserClosure}
; '$lgt_comp_ctx_entity'(Ctx, Entity), Entity == user,
\+ '$lgt_control_construct'(Closure),
UserClosure = Closure
),
% goal or closure called in "user"
!,
'$lgt_check'(var_or_callable, UserClosure).
'$lgt_compile_static_binding_meta_argument'(N, Closure, _, Ctx, TClosure) :-
integer(N), N > 0,
% closure
!,
'$lgt_check'(var_or_callable, Closure),
'$lgt_length'(ExtArgs, 0, N),
'$lgt_extend_closure'(Closure, ExtArgs, Goal, Ctx),
% compiling the meta-argument allows predicate cross-referencing information
% to be collected even if the compilation result cannot be used
'$lgt_compile_body'(Goal, meta, TGoal, _, Ctx),
functor(TGoal, TFunctor, _),
( Goal == TGoal ->
\+ '$lgt_control_construct'(TGoal),
% either a built-in predicate or a predicate called in "user"
TClosure = {Closure}
; sub_atom(TFunctor, 0, 5, _, '$lgt_') ->
% in some backend Prolog systems, internal Logtalk compiler/runtime
% predicates may be marked as built-in predicates
fail
; '$lgt_built_in_predicate'(TGoal) ->
\+ '$lgt_control_construct'(TGoal),
% built-in predicates may result from goal-expansion during
% compilation or from inlining of user predicate definitions
'$lgt_built_in_goal_to_closure'(N, TGoal, TFunctor, TArgs),
TClosure0 =.. [TFunctor| TArgs],
TClosure = {TClosure0}
; '$lgt_user_goal_to_closure'(N, TGoal, TFunctor, TArgs, ExCtx) ->
TClosure = '$lgt_closure'(TFunctor, TArgs, ExCtx)
; % runtime resolved meta-call
fail
).
'$lgt_compile_static_binding_meta_argument'(0, Goal, _, Ctx, {TGoal}) :-
% the {}/1 construct signals a pre-compiled metacall
'$lgt_compile_body'(Goal, meta, TGoal, _, Ctx).
'$lgt_built_in_goal_to_closure'(N, TGoal, TFunctor, TArgs) :-
functor(TGoal, TFunctor, TArity),
TGoal =.. [TFunctor| TAllArgs],
% subtract the number of extra arguments
Arity is TArity - N,
Arity >= 0,
% unify the compiled closure arguments from the compiled goal arguments
'$lgt_length'(TArgs, 0, Arity),
'$lgt_append'(TArgs, _, TAllArgs),
!.
'$lgt_user_goal_to_closure'(N, TGoal, TFunctor, TArgs, ExCtx) :-
functor(TGoal, TFunctor, TArity),
TGoal =.. [TFunctor| TAllArgs],
% subtract the number of extra arguments and the execution context argument
Arity is TArity - N - 1,
Arity >= 0,
% unify the compiled closure arguments from the compiled goal arguments
'$lgt_length'(TArgs, 0, Arity),
'$lgt_append'(TArgs, _, TAllArgs),
% unify the execution context argument using the compiled goal
arg(TArity, TGoal, ExCtx),
!.
% '$lgt_obj_super_call_static_binding'(@object_identifier, @callable, @execution_context, -callable)
%
% static binding for the (^^)/1 control construct (used within objects)
'$lgt_obj_super_call_static_binding'(Obj, Pred, ExCtx, Call) :-
( '$lgt_pp_imported_category_'(_, _, _, _, _, _),
'$lgt_obj_super_call_static_binding_category'(Obj, Pred, ExCtx, Call) ->
true
; '$lgt_pp_extended_object_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_obj_super_call_static_binding_prototype'(Obj, Pred, ExCtx, Call)
; '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _),
'$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_obj_super_call_static_binding_instance_class'(Obj, Pred, ExCtx, Call)
; '$lgt_pp_instantiated_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_obj_super_call_static_binding_instance'(Obj, Pred, ExCtx, Call)
; '$lgt_pp_specialized_class_'(_, _, _, _, _, _, _, _, _, _, _) ->
'$lgt_obj_super_call_static_binding_class'(Obj, Pred, ExCtx, Call)
; fail
).
'$lgt_obj_super_call_static_binding_category'(Obj, Alias, OExCtx, Call) :-
% when working with parametric entities, we must connect the parameters
% between related entities
'$lgt_pp_runtime_clause_'('$lgt_imports_category_'(Obj, Ctg, _)),
'$lgt_current_category_'(Ctg, _, Dcl, Def, _, _),
% we may be aliasing the predicate
( '$lgt_pp_predicate_alias_'(Ctg, Pred, Alias, _, _, _) ->
true
; Pred = Alias
),
% lookup predicate declaration
call(Dcl, Pred, _, _, Flags, DclCtn), !,
% the predicate must be static
Flags /\ 2 =:= 0,
% unify execution context arguments
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, CExCtx, Obj, Ctg),
% lookup predicate definition
call(Def, Pred, CExCtx, Call, DefCtn), !,
% predicate definition found; use it only if it's safe
'$lgt_static_binding_safe_paths'(Obj, DclCtn, DefCtn).
'$lgt_obj_super_call_static_binding_prototype'(Obj, Alias, OExCtx, Call) :-
% when working with parametric entities, we must connect the parameters
% between related entities
'$lgt_pp_runtime_clause_'('$lgt_extends_object_'(Obj, Parent, RelationScope)),
'$lgt_current_object_'(Parent, _, Dcl, Def, _, _, _, _, _, _, _),
% we may be aliasing the predicate
( '$lgt_pp_predicate_alias_'(Parent, Pred, Alias, _, _, _) ->
true
; Pred = Alias
),
% lookup predicate declaration
( RelationScope == (public) ->
call(Dcl, Pred, Scope, _, Flags, SCtn, TCtn)
; RelationScope == protected ->
call(Dcl, Pred, PredScope, _, Flags, SCtn, TCtn),
'$lgt_filter_scope'(PredScope, Scope)
; Scope = p,
call(Dcl, Pred, PredScope, _, Flags, SCtn0, TCtn),
'$lgt_filter_scope_container'(PredScope, SCtn0, Obj, SCtn)
), !,
% check that the call is within scope (i.e. public or protected)
( Scope = p(_) ->
true
; Obj = SCtn
),
% the predicate must be static
Flags /\ 2 =:= 0,
% unify execution context arguments
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, PExCtx, Parent, Parent),
% lookup predicate definition
call(Def, Pred, PExCtx, Call, _, DefCtn), !,
% predicate definition found; use it only if it's safe
'$lgt_static_binding_safe_paths'(Obj, TCtn, DefCtn).
'$lgt_obj_super_call_static_binding_instance'(Obj, Alias, OExCtx, Call) :-
% when working with parametric entities, we must connect the parameters
% between related entities
'$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(Obj, Class, RelationScope)),
'$lgt_current_object_'(Class, _, _, _, _, IDcl, IDef, _, _, _, _),
% we may be aliasing the predicate
( '$lgt_pp_predicate_alias_'(Class, Pred, Alias, _, _, _) ->
true
; Pred = Alias
),
% lookup predicate declaration
( RelationScope == (public) ->
call(IDcl, Pred, Scope, _, Flags, SCtn, TCtn)
; RelationScope == protected ->
call(IDcl, Pred, PredScope, _, Flags, SCtn, TCtn),
'$lgt_filter_scope'(PredScope, Scope)
; Scope = p,
call(IDcl, Pred, PredScope, _, Flags, SCtn0, TCtn),
'$lgt_filter_scope_container'(PredScope, SCtn0, Obj, SCtn)
), !,
% check that the call is within scope (i.e. public or protected)
( Scope = p(_) ->
true
; Obj = SCtn
),
% the predicate must be static
Flags /\ 2 =:= 0,
% unify execution context arguments
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, CExCtx, Class, Class),
% lookup predicate definition
call(IDef, Pred, CExCtx, Call, _, DefCtn), !,
% predicate definition found; use it only if it's safe
'$lgt_static_binding_safe_paths'(Obj, TCtn, DefCtn).
'$lgt_obj_super_call_static_binding_class'(Obj, Alias, OExCtx, Call) :-
% when working with parametric entities, we must connect the parameters
% between related entities
'$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(Obj, Superclass, RelationScope)),
'$lgt_current_object_'(Superclass, _, _, _, _, IDcl, IDef, _, _, _, _),
% we may be aliasing the predicate
( '$lgt_pp_predicate_alias_'(Superclass, Pred, Alias, _, _, _) ->
true
; Pred = Alias
),
% lookup predicate declaration
( RelationScope == (public) ->
call(IDcl, Pred, Scope, _, Flags, SCtn, TCtn)
; RelationScope == protected ->
call(IDcl, Pred, PredScope, _, Flags, SCtn, TCtn),
'$lgt_filter_scope'(PredScope, Scope)
; Scope = p,
call(IDcl, Pred, PredScope, _, Flags, SCtn0, TCtn),
'$lgt_filter_scope_container'(PredScope, SCtn0, Obj, SCtn)
), !,
% check that the call is within scope (i.e. public or protected)
( Scope = p(_) ->
true
; Obj = SCtn
),
% the predicate must be static
Flags /\ 2 =:= 0,
% unify execution context arguments
'$lgt_execution_context_update_this_entity'(OExCtx, Obj, Obj, SExCtx, Superclass, Superclass),
% lookup predicate definition
call(IDef, Pred, SExCtx, Call, _, DefCtn), !,
% predicate definition found; use it only if it's safe
'$lgt_static_binding_safe_paths'(Obj, TCtn, DefCtn).
'$lgt_obj_super_call_static_binding_instance_class'(Obj, Pred, ExCtx, Call) :-
( '$lgt_obj_super_call_static_binding_instance'(Obj, Pred, ExCtx, ICall),
'$lgt_obj_super_call_static_binding_class'(Obj, Pred, ExCtx, CCall) ->
( ICall == CCall ->
Call = ICall
; '$lgt_execution_context'(ExCtx, _, _, _, Self, _, _),
Call = (Obj = Self -> ICall; CCall)
)
; '$lgt_obj_super_call_static_binding_instance'(Obj, Pred, ExCtx, Call) ->
true
; '$lgt_obj_super_call_static_binding_class'(Obj, Pred, ExCtx, Call)
).
% '$lgt_ctg_super_call_static_binding'(@category_identifier, @callable, @execution_context, -callable)
%
% static binding for the (^^)/1 control construct (used within categories)
'$lgt_ctg_super_call_static_binding'(Ctg, Alias, CExCtx, Call) :-
% when working with parametric entities, we must connect the parameters
% between related entities
'$lgt_pp_runtime_clause_'('$lgt_extends_category_'(Ctg, ExtCtg, RelationScope)),
'$lgt_current_category_'(ExtCtg, _, Dcl, Def, _, _),
% we may be aliasing the predicate
( '$lgt_pp_predicate_alias_'(ExtCtg, Pred, Alias, _, _, _) ->
true
; Pred = Alias
),
% lookup predicate declaration
( RelationScope == (public) ->
call(Dcl, Pred, Scope, _, Flags, DclCtn)
; RelationScope == protected,
call(Dcl, Pred, Scope0, _, Flags, DclCtn),
'$lgt_filter_scope'(Scope0, Scope)
), !,
% check that the call is within scope
Scope = p(_),
% the predicate must be static
Flags /\ 2 =:= 0,
% unify execution context arguments
'$lgt_execution_context_update_this_entity'(CExCtx, This, Ctg, EExCtx, This, ExtCtg),
% lookup predicate definition
call(Def, Pred, EExCtx, Call, DefCtn), !,
% predicate definition found; use it only if it's safe
'$lgt_static_binding_safe_paths'(Ctg, DclCtn, DefCtn).
% '$lgt_send_to_obj_db_msg_static_binding'(@category_identifier, @callable, -callable)
%
% static binding for selected database messages sent to an object
'$lgt_send_to_obj_db_msg_static_binding'(Obj, Head, THead) :-
'$lgt_current_object_'(Obj, _, Dcl, Def, _, _, _, _, _, _, ObjFlags),
% check that the object is not compiled in debug mode
ObjFlags /\ 512 =\= 512,
% check that the object is static
ObjFlags /\ 2 =:= 0,
call(Dcl, Head, Scope, _, PredFlags, SCtn, DCtn), !,
% check that the call is within scope
Scope = p(p(_)),
% check that the predicate is dynamic
PredFlags /\ 2 =:= 2,
% check that we're acting on the same entity that declares the predicate dynamic
SCtn = Obj,
% lookup local predicate definition
call(Def, Head, _, THead), !,
% predicate definition found; use it only if it's safe
'$lgt_static_binding_entity'(DCtn).
% '$lgt_static_binding_safe_paths'(@entity_identifier, @entity_identifier, @entity_identifier)
%
% all ancestor entities up to the starting point for both the declaration
% container and the definition container must be static-binding entities
'$lgt_static_binding_safe_paths'(Entity, DclEntity, DefEntity) :-
( DclEntity \= Entity ->
'$lgt_static_binding_entity'(DclEntity)
; true
),
( DefEntity \= Entity ->
'$lgt_static_binding_entity'(DefEntity)
; true
),
'$lgt_static_binding_safe_declaration_ancestors'(Entity, DclEntity),
'$lgt_static_binding_safe_definition_ancestors'(Entity, DefEntity).
'$lgt_static_binding_entity'(Entity) :-
( '$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, Flags) ->
Flags /\ 64 =\= 64,
Flags /\ 32 =\= 32
% support for complementing categories is disabled
; '$lgt_current_protocol_'(Entity, _, _, _, Flags) ->
true
; '$lgt_current_category_'(Entity, _, _, _, _, Flags)
),
Flags /\ 512 =\= 512,
% entity is not compiled in debug mode
Flags /\ 2 =:= 0.
% entity is static
'$lgt_static_binding_entity'(object, Object) :-
'$lgt_current_object_'(Object, _, _, _, _, _, _, _, _, _, Flags),
Flags /\ 512 =\= 512,
% object is not compiled in debug mode
Flags /\ 2 =:= 0,
% object is static
Flags /\ 64 =\= 64,
Flags /\ 32 =\= 32.
% support for complementing categories is disallowed
'$lgt_static_binding_entity'(protocol, Protocol) :-
'$lgt_current_protocol_'(Protocol, _, _, _, Flags),
Flags /\ 512 =\= 512,
% protocol is not compiled in debug mode
Flags /\ 2 =:= 0.
% protocol is static
'$lgt_static_binding_entity'(category, Category) :-
'$lgt_current_category_'(Category, _, _, _, _, Flags),
Flags /\ 512 =\= 512,
% category is not compiled in debug mode
Flags /\ 2 =:= 0.
% category is static
'$lgt_static_binding_safe_declaration_ancestors'(Entity, DclEntity) :-
( Entity = DclEntity ->
% local predicate declaration
true
; % we add a third argument to properly handle class hierarchies if necessary
'$lgt_static_binding_safe_declaration_ancestors'(Entity, DclEntity, _) ->
% ensure no spurious choice-points
true
; fail
).
'$lgt_static_binding_safe_declaration_ancestors'(Entity, DclEntity, Kind) :-
'$lgt_entity_ancestor'(Entity, Type, Ancestor, Kind, NextKind),
( '$lgt_static_binding_entity'(Type, Ancestor) ->
( Ancestor = DclEntity ->
true
; % move up, implementing the same depth-first strategy used by the predicate
% declaration lookup algorithm
'$lgt_static_binding_safe_declaration_ancestors'(Ancestor, DclEntity, NextKind)
)
; % ancestor can be later modified, rendering the static binding optimization invalid
!,
fail
).
'$lgt_static_binding_safe_definition_ancestors'(Entity, DefEntity) :-
( Entity = DefEntity ->
% local predicate definition
true
; % we add a third argument to properly handle class hierarchies if necessary
'$lgt_static_binding_safe_definition_ancestors'(Entity, DefEntity, _) ->
% ensure no spurious choice-points
true
; fail
).
'$lgt_static_binding_safe_definition_ancestors'(Entity, DefEntity, Kind) :-
'$lgt_entity_ancestor'(Entity, Type, Ancestor, Kind, NextKind),
% protocols cannot contain predicate definitions
Type \== protocol,
( '$lgt_static_binding_entity'(Type, Ancestor) ->
( Ancestor = DefEntity ->
true
; % move up, implementing the same depth-first strategy used by the predicate
% definition lookup algorithm
'$lgt_static_binding_safe_definition_ancestors'(Ancestor, DefEntity, NextKind)
)
; % ancestor can be later modified, rendering the static binding optimization invalid
!,
fail
).
% entity ancestors are generated on backtracking in the same order
% used by the predicate declaration and definition lookup algorithms
'$lgt_entity_ancestor'(Entity, protocol, Protocol, Kind, Kind) :-
'$lgt_implements_protocol_'(Entity, Protocol, _).
'$lgt_entity_ancestor'(Entity, protocol, Protocol, Kind, Kind) :-
'$lgt_pp_runtime_clause_'('$lgt_implements_protocol_'(Entity, Protocol, _)).
'$lgt_entity_ancestor'(Entity, protocol, Protocol, protocol, protocol) :-
'$lgt_extends_protocol_'(Entity, Protocol, _).
'$lgt_entity_ancestor'(Entity, protocol, Protocol, protocol, protocol) :-
'$lgt_pp_runtime_clause_'('$lgt_extends_protocol_'(Entity, Protocol, _)).
'$lgt_entity_ancestor'(Entity, category, Category, category, category) :-
'$lgt_extends_category_'(Entity, Category, _).
'$lgt_entity_ancestor'(Entity, category, Category, category, category) :-
'$lgt_pp_runtime_clause_'('$lgt_extends_category_'(Entity, Category, _)).
'$lgt_entity_ancestor'(Entity, category, Category, Kind, Kind) :-
'$lgt_imports_category_'(Entity, Category, _).
'$lgt_entity_ancestor'(Entity, category, Category, Kind, Kind) :-
'$lgt_pp_runtime_clause_'('$lgt_imports_category_'(Entity, Category, _)).
'$lgt_entity_ancestor'(Entity, object, Parent, prototype, prototype) :-
'$lgt_extends_object_'(Entity, Parent, _).
'$lgt_entity_ancestor'(Entity, object, Parent, prototype, prototype) :-
'$lgt_pp_runtime_clause_'('$lgt_extends_object_'(Entity, Parent, _)).
'$lgt_entity_ancestor'(Entity, object, Class, instance, superclass) :-
'$lgt_instantiates_class_'(Entity, Class, _).
'$lgt_entity_ancestor'(Entity, object, Class, instance, superclass) :-
'$lgt_pp_runtime_clause_'('$lgt_instantiates_class_'(Entity, Class, _)).
'$lgt_entity_ancestor'(Entity, object, Superclass, superclass, superclass) :-
'$lgt_specializes_class_'(Entity, Superclass, _).
'$lgt_entity_ancestor'(Entity, object, Superclass, superclass, superclass) :-
'$lgt_pp_runtime_clause_'('$lgt_specializes_class_'(Entity, Superclass, _)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% utility predicates
%
% although usually provided as either built-in or library predicates by the
% backends, it's simpler and more portable to define our own versions
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% '$lgt_length'(+list, +integer, -integer)
% '$lgt_length'(-list, +integer, +integer)
'$lgt_length'([], Length, Length) :-
!.
'$lgt_length'([_| Tail], Length0, Length) :-
Length1 is Length0 + 1,
'$lgt_length'(Tail, Length1, Length).
'$lgt_append'([], List, List).
'$lgt_append'([Head| Tail], List, [Head| Tail2]) :-
'$lgt_append'(Tail, List, Tail2).
'$lgt_member'(Head, [Head| _]).
'$lgt_member'(Head, [_| Tail]) :-
'$lgt_member'(Head, Tail).
'$lgt_member_var'(V, [H| _]) :-
V == H.
'$lgt_member_var'(V, [_| T]) :-
nonvar(T),
'$lgt_member_var'(V, T).
'$lgt_memberchk_var'(Element, [Head| Tail]) :-
( Element == Head ->
true
; '$lgt_memberchk_var'(Element, Tail)
).
'$lgt_sub_term_var'(SubTerm, Term) :-
SubTerm == Term,
!.
'$lgt_sub_term_var'(SubTerm, Term) :-
compound(Term),
functor(Term, _, Arity),
'$lgt_between'(1, Arity, N),
arg(N, Term, Argument),
'$lgt_sub_term_var'(SubTerm, Argument),
!.
'$lgt_anonymous_or_singleton_variable'(Variable, VariableNames, Singletons) :-
( '$lgt_member'(Name0=Variable0, Singletons),
Variable0 == Variable,
\+ '$lgt_parameter_variable_name'(Name0) ->
true
; \+ (
'$lgt_member'(_=Variable0, VariableNames),
Variable0 == Variable
)
).
'$lgt_anonymous_or_singleton_variables'([], _, _).
'$lgt_anonymous_or_singleton_variables'([Variable| Variables], VariableNames, Singletons) :-
'$lgt_anonymous_or_singleton_variable'(Variable, VariableNames, Singletons),
'$lgt_anonymous_or_singleton_variables'(Variables, VariableNames, Singletons).
% find position-relevant argument pairs for =../2 lint checks where a relevant
% argument is either a bound argument or a named variable argument; the last
% argument returns the type of list (open or closed)
'$lgt_position_relevant_argument_pairs'([], _, _, [], closed, []).
'$lgt_position_relevant_argument_pairs'([Argument| Arguments], N, VariableNames, [N-Argument| Pairs], Type, Tail) :-
once((
nonvar(Argument)
; '$lgt_member'(_=Argument0, VariableNames),
Argument0 == Argument
)),
!,
( var(Arguments) ->
% open list
Pairs = [],
Type = open,
Tail = Arguments
; M is N + 1,
'$lgt_position_relevant_argument_pairs'(Arguments, M, VariableNames, Pairs, Type, Tail)
).
'$lgt_position_relevant_argument_pairs'([_| Arguments], N, VariableNames, Pairs, Type, Tail) :-
( var(Arguments) ->
% open list
Pairs = [],
Type = open,
Tail = Arguments
; M is N + 1,
'$lgt_position_relevant_argument_pairs'(Arguments, M, VariableNames, Pairs, Type, Tail)
).
'$lgt_between'(Lower, Upper, N) :-
Lower =< Upper,
'$lgt_between_aux'(Lower, Upper, N).
'$lgt_between_aux'(Lower, _, Lower).
'$lgt_between_aux'(Lower, Upper, N) :-
Lower < Upper,
Next is Lower + 1,
'$lgt_between_aux'(Next, Upper, N).
'$lgt_is_list_or_partial_list'(Var) :-
var(Var),
!.
'$lgt_is_list_or_partial_list'([]).
'$lgt_is_list_or_partial_list'([_| Tail]) :-
'$lgt_is_list_or_partial_list'(Tail).
'$lgt_is_list'((-)) :-
!,
fail.
'$lgt_is_list'([]).
'$lgt_is_list'([_| Tail]) :-
'$lgt_is_list'(Tail).
'$lgt_is_boolean'((-)) :-
!,
fail.
'$lgt_is_boolean'(true).
'$lgt_is_boolean'(false).
'$lgt_intersection'(_, [], []) :- !.
'$lgt_intersection'([], _, []) :- !.
'$lgt_intersection'([Head1| Tail1], List2, Intersection) :-
( '$lgt_memberchk_var'(Head1, List2) ->
Intersection = [Head1| IntersectionRest],
'$lgt_intersection'(Tail1, List2, IntersectionRest)
; '$lgt_intersection'(Tail1, List2, Intersection)
).
'$lgt_var_subtract'([], _, []).
'$lgt_var_subtract'([Head| Tail], List, Rest) :-
( '$lgt_memberchk_var'(Head, List) ->
'$lgt_var_subtract'(Tail, List, Rest)
; Rest = [Head| Tail2],
'$lgt_var_subtract'(Tail, List, Tail2)
).
'$lgt_sum_list'(List, Sum) :-
'$lgt_sum_list'(List, 0, Sum).
'$lgt_sum_list'([], Sum, Sum).
'$lgt_sum_list'([Value| Values], Sum0, Sum) :-
Sum1 is Sum0 + Value,
'$lgt_sum_list'(Values, Sum1, Sum).
'$lgt_select'(Head, [Head| Tail], Tail).
'$lgt_select'(Head, [Head2| Tail], [Head2| Tail2]) :-
'$lgt_select'(Head, Tail, Tail2).
% definition taken from the SWI-Prolog documentation
'$lgt_variant'(Term1, Term2) :-
% avoid trouble in any shared variables
copy_term(Term1, Term1Copy),
copy_term(Term2, Term2Copy),
% ground and compare the term copies
numbervars(Term1Copy, 0, N),
numbervars(Term2Copy, 0, N),
Term1Copy == Term2Copy.
% variable aliasing occurs in a head of a clause
% when two or more arguments share variables
'$lgt_variable_aliasing'(Head) :-
compound(Head),
Head =.. [_| Arguments],
'$lgt_select'(Argument1, Arguments, OtherArguments),
'$lgt_member'(Argument2, OtherArguments),
term_variables(Argument1, Variables1),
term_variables(Argument2, Variables2),
'$lgt_intersection'(Variables1, Variables2, [_| _]),
% at least one variable in common
!.
'$lgt_read_file_to_terms'(File, Directory, SourceFile, Terms, Mode) :-
% check file specification and expand library notation or environment variable if used
catch(
'$lgt_check_and_expand_source_file'(File, ExpandedFile),
error(FileError, _),
throw(FileError)
),
% find the full file name as the extension may be missing
( '$lgt_source_file_name'(ExpandedFile, [], Directory, _, _, SourceFile),
% avoid a loading loop by checking that the file name is different
% from the name of the file containing the include/1 directive
\+ '$lgt_pp_file_paths_flags_'(_, _, SourceFile, _, _),
'$lgt_file_exists'(SourceFile) ->
true
; '$lgt_source_file_name'(ExpandedFile, [], Directory, _, _, SourceFile),
'$lgt_pp_file_paths_flags_'(_, _, SourceFile, _, _) ->
throw(permission_error(include, file, File))
; throw(existence_error(file, File))
),
( Mode = compile(_,_,_) ->
'$lgt_print_message'(silent(compiling), compiling_file(SourceFile, []))
; true
),
catch(
'$lgt_open'(SourceFile, read, Stream, []),
error(OpenError, _),
throw(OpenError)
),
% look for an encoding/1 directive that, when present, must be the first term on a source file
catch(
'$lgt_read_term'(Stream, Term, [variable_names(VariableNames), singletons(Singletons)], Lines),
error(TermError, _),
'$lgt_read_file_to_terms_error_handler'(Mode, SourceFile, Stream, TermError)
),
catch(
'$lgt_check_for_encoding_directive'(Term, SourceFile, Lines, Stream, NewStream, [], _),
FirstTermError,
'$lgt_read_file_to_terms_error_handler'(Mode, SourceFile, Stream, FirstTermError)
),
% read the reamining terms
catch(
'$lgt_read_stream_to_terms'(Term, VariableNames, Singletons, Lines, SourceFile, NewStream, Terms, Mode),
error(TermError, _),
'$lgt_read_file_to_terms_error_handler'(Mode, SourceFile, NewStream, TermError)
),
'$lgt_close'(NewStream).
'$lgt_read_file_to_terms_error_handler'(runtime, _, Stream, Error) :-
'$lgt_close'(Stream),
throw(Error).
'$lgt_read_file_to_terms_error_handler'(compile(_,_,_), SourceFile, Stream, Error) :-
'$lgt_pp_file_paths_flags_'(_, _, _, ObjectFile, _),
( '$lgt_stream_current_line_number'(Stream, Line) ->
true
; Line = -1
),
'$lgt_close'(Stream),
'$lgt_compiler_error_handler'(SourceFile, ObjectFile, Line-Line, Error).
'$lgt_read_stream_to_terms'(Term, VariableNames, Singletons, Lines, File, Stream, [Term-sd(VariableNames,Singletons,Lines)| Terms], Mode) :-
var(Term),
% delay the instantiation error
!,
'$lgt_read_term'(Stream, NextTerm, [variable_names(NextVariableNames), singletons(NextSingletons)], NextLines),
'$lgt_read_stream_to_terms'(NextTerm, NextVariableNames, NextSingletons, NextLines, File, Stream, Terms, Mode).
'$lgt_read_stream_to_terms'(end_of_file, _, _, _, _, _, [], _) :-
!.
'$lgt_read_stream_to_terms'((:- op(Priority, Specifier, Operators)), VariableNames, Singletons, Lines, File, Stream, [(:- op(Priority, Specifier, Operators))-sd(VariableNames,Singletons,Lines)| Terms], Mode) :-
!,
'$lgt_check'(operator_specification, op(Priority, Specifier, Operators)),
( '$lgt_pp_entity_'(_, _, _) ->
'$lgt_activate_entity_operators'(Priority, Specifier, Operators, l, File, Lines, Mode)
; '$lgt_activate_file_operators'(Priority, Specifier, Operators, Mode)
),
'$lgt_read_term'(Stream, NextTerm, [variable_names(NextVariableNames), singletons(NextSingletons)], NextLines),
'$lgt_read_stream_to_terms'(NextTerm, NextVariableNames, NextSingletons, NextLines, File, Stream, Terms, Mode).
'$lgt_read_stream_to_terms'(Term, VariableNames, Singletons, Lines, File, Stream, [Term-sd(VariableNames,Singletons,Lines)| Terms], Mode) :-
'$lgt_report_singleton_variables'(Mode, Singletons, Term, File, Lines),
'$lgt_read_term'(Stream, NextTerm, [variable_names(NextVariableNames), singletons(NextSingletons)], NextLines),
'$lgt_read_stream_to_terms'(NextTerm, NextVariableNames, NextSingletons, NextLines, File, Stream, Terms, Mode).
% '$lgt_check'(+atom, @term, @callable)
%
% type-checking for built-in directive and predicate arguments
'$lgt_check'(var, Term, Context) :-
( var(Term) ->
true
; throw(error(uninstantiation_error(Term), Context))
).
'$lgt_check'(nonvar, Term, Context) :-
( nonvar(Term) ->
true
; throw(error(instantiation_error, Context))
).
'$lgt_check'(ground, Term, Context) :-
( ground(Term) ->
true
; throw(error(instantiation_error, Context))
).
'$lgt_check'(atom, Term, Context) :-
( atom(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(var_or_atom, Term, Context) :-
( var(Term) ->
true
; atom(Term) ->
true
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(boolean, Term, Context) :-
( Term == true ->
true
; Term == false ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; atom(Term) ->
throw(error(domain_error(boolean, Term), Context))
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(var_or_boolean, Term, Context) :-
( var(Term) ->
true
; \+ atom(Term) ->
throw(error(type_error(atom, Term), Context))
; Term \== true,
Term \== false,
throw(error(domain_error(boolean, Term), Context))
).
'$lgt_check'(atom_or_string, Term, Context) :-
( atom(Term) ->
true
; '$lgt_string'(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(atom_or_string, Term), Context))
).
'$lgt_check'(integer, Term, Context) :-
( integer(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(integer, Term), Context))
).
'$lgt_check'(var_or_integer, Term, Context) :-
( var(Term) ->
true
; integer(Term) ->
true
; throw(error(type_error(integer, Term), Context))
).
'$lgt_check'(non_negative_integer, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; \+ integer(Term) ->
throw(error(type_error(integer, Term), Context))
; Term < 0 ->
throw(error(domain_error(not_less_than_zero, Term), Context))
; true
).
'$lgt_check'(var_or_non_negative_integer, Term, Context) :-
( var(Term) ->
true
; \+ integer(Term) ->
throw(error(type_error(integer, Term), Context))
; Term < 0 ->
throw(error(domain_error(not_less_than_zero, Term), Context))
; true
).
'$lgt_check'(float, Term, Context) :-
( float(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(float, Term), Context))
).
'$lgt_check'(atomic, Term, Context) :-
( atomic(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(atomic, Term), Context))
).
'$lgt_check'(atomic_or_string, Term, Context) :-
( atomic(Term) ->
true
; '$lgt_string'(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(atomic_or_string, Term), Context))
).
'$lgt_check'(curly_bracketed_term, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; Term = {_} ->
true
; Term == '{}' ->
true
; throw(error(type_error(curly_bracketed_term, Term), Context))
).
'$lgt_check'(var_or_curly_bracketed_term, Term, Context) :-
( var(Term) ->
true
; Term = {_} ->
true
; Term == '{}' ->
true
; throw(error(type_error(curly_bracketed_term, Term), Context))
).
'$lgt_check'(callable, Term, Context) :-
( callable(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(var_or_callable, Term, Context) :-
( var(Term) ->
true
; callable(Term) ->
true
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(qualified_callable, Term, Context) :-
( '$lgt_prolog_feature'(modules, supported) ->
'$lgt_check'(qualified_callable_, Term, Context)
; '$lgt_check'(callable, Term, Context)
).
'$lgt_check'(qualified_callable_, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; Term = ':'(Module, Goal) ->
'$lgt_check'(module_identifier, Module, Context),
'$lgt_check'(qualified_callable_, Goal, Context)
; callable(Term) ->
true
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(clause, Term, Context) :-
( Term = (Head :- Body) ->
'$lgt_check'(callable, Head, Context),
'$lgt_check'(var_or_callable, Body, Context)
; callable(Term) ->
true
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(list, Term, Context) :-
'$lgt_check_list'(list, Term, Term, Context).
'$lgt_check'(list_or_partial_list, Term, Context) :-
( var(Term) ->
true
; '$lgt_is_list_or_partial_list'(Term) ->
true
; throw(error(type_error(list, Term), Context))
).
'$lgt_check'(list(Type), Term, Context) :-
'$lgt_check_list'(list(Type), Term, Term, Context),
forall('$lgt_member'(Item, Term), '$lgt_check'(Type, Item, Context)).
'$lgt_check'(object, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; '$lgt_current_object_'(Term, _, _, _, _, _, _, _, _, _, _) ->
true
; callable(Term) ->
throw(error(existence_error(object, Term), Context))
; throw(error(type_error(object_identifier, Term), Context))
).
'$lgt_check'(object_identifier, Term, Context) :-
( callable(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(object_identifier, Term), Context))
).
'$lgt_check'(var_or_object_identifier, Term, Context) :-
( var(Term) ->
true
; callable(Term) ->
true
; throw(error(type_error(object_identifier, Term), Context))
).
'$lgt_check'(protocol, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; '$lgt_current_protocol_'(Term, _, _, _, _) ->
true
; atom(Term) ->
throw(error(existence_error(protocol, Term), Context))
; throw(error(type_error(protocol_identifier, Term), Context))
).
'$lgt_check'(protocol_identifier, Term, Context) :-
( atom(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(protocol_identifier, Term), Context))
).
'$lgt_check'(var_or_protocol_identifier, Term, Context) :-
( var(Term) ->
true
; atom(Term) ->
true
; throw(error(type_error(protocol_identifier, Term), Context))
).
'$lgt_check'(category, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; '$lgt_current_category_'(Term, _, _, _, _, _) ->
true
; callable(Term) ->
throw(error(existence_error(category, Term), Context))
; throw(error(type_error(category_identifier, Term), Context))
).
'$lgt_check'(category_identifier, Term, Context) :-
( callable(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(category_identifier, Term), Context))
).
'$lgt_check'(var_or_category_identifier, Term, Context) :-
( var(Term) ->
true
; callable(Term) ->
true
; throw(error(type_error(category_identifier, Term), Context))
).
'$lgt_check'(entity_identifier, Term, Context) :-
( callable(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(entity_identifier, Term), Context))
).
'$lgt_check'(var_or_entity_identifier, Term, Context) :-
( var(Term) ->
true
; callable(Term) ->
true
; throw(error(type_error(entity_identifier, Term), Context))
).
'$lgt_check'(module_identifier, Term, Context) :-
( atom(Term) ->
true
; var(Term) ->
throw(error(instantiation_error, Context))
; throw(error(type_error(module_identifier, Term), Context))
).
'$lgt_check'(var_or_module_identifier, Term, Context) :-
( var(Term) ->
true
; atom(Term) ->
true
; throw(error(type_error(module_identifier, Term), Context))
).
'$lgt_check'(predicate_indicator, Term, Context) :-
( Term = Functor/Arity ->
'$lgt_check'(atom, Functor, Context),
'$lgt_check'(non_negative_integer, Arity, Context)
; throw(error(type_error(predicate_indicator, Term), Context))
).
'$lgt_check'(var_or_predicate_indicator, Term, Context) :-
( var(Term) ->
true
; Term = Functor/Arity ->
'$lgt_check'(var_or_atom, Functor, Context),
'$lgt_check'(var_or_non_negative_integer, Arity, Context)
; throw(error(type_error(predicate_indicator, Term), Context))
).
'$lgt_check'(predicate_or_non_terminal_indicator, Term, Context) :-
( Term = Functor/Arity ->
'$lgt_check'(atom, Functor, Context),
'$lgt_check'(non_negative_integer, Arity, Context)
; Term = Functor//Arity ->
'$lgt_check'(atom, Functor, Context),
'$lgt_check'(non_negative_integer, Arity, Context)
; throw(error(type_error(predicate_indicator, Term), Context))
).
'$lgt_check'(scope, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; '$lgt_valid_scope'(Term) ->
true
; atom(Term) ->
throw(error(domain_error(scope, Term), Context))
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(var_or_scope, Term, Context) :-
( var(Term) ->
true
; '$lgt_valid_scope'(Term) ->
true
; atom(Term) ->
throw(error(domain_error(scope, Term), Context))
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(var_or_event, Term, Context) :-
( var(Term) ->
true
; Term \== before,
Term \== after ->
throw(error(type_error(event, Term), Context))
; true
).
'$lgt_check'(operator_specification, Term, Context) :-
( Term = op(Priority, Specifier, Operators) ->
'$lgt_check'(operator_priority, Priority, Context),
'$lgt_check'(operator_specifier, Specifier, Context),
'$lgt_check'(operator_names, Operators, Context)
; throw(error(type_error(operator_specification, Term), Context))
).
'$lgt_check'(operator_priority, Priority, Context) :-
( var(Priority) ->
throw(error(instantiation_error, Context))
; \+ integer(Priority),
throw(error(type_error(integer, Priority), Context))
; (Priority < 0; Priority > 1200) ->
throw(error(domain_error(operator_priority, Priority), Context))
; true
).
'$lgt_check'(var_or_operator_priority, Priority, Context) :-
( var(Priority) ->
true
; '$lgt_check'(operator_priority, Priority, Context)
).
'$lgt_check'(operator_specifier, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; \+ atom(Term) ->
throw(error(type_error(atom, Term), Context))
; '$lgt_member'(Term, [fx, fy, xfx, xfy, yfx, xf, yf]) ->
true
; throw(error(domain_error(operator_specifier, Term), Context))
).
'$lgt_check'(var_or_operator_specifier, Term, Context) :-
( var(Term) ->
true
; '$lgt_check'(operator_specifier, Term, Context)
).
'$lgt_check'(operator_names, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; Term == (',') ->
throw(error(permission_error(modify, operator, ','), Context))
; atom(Term) ->
true
; \+ '$lgt_is_list'(Term) ->
throw(type_error(list, Term))
; \+ ('$lgt_member'(Operator, Term), \+ '$lgt_check'(operator_name, Operator, Context))
).
'$lgt_check'(operator_name, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; Term == (',') ->
throw(error(permission_error(modify, operator, ','), Context))
; atom(Term) ->
true
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(var_or_object_property, Term, Context) :-
( var(Term) ->
true
; '$lgt_valid_object_property'(Term) ->
true
; callable(Term) ->
throw(error(domain_error(object_property, Term), Context))
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(var_or_category_property, Term, Context) :-
( var(Term) ->
true
; '$lgt_valid_category_property'(Term) ->
true
; callable(Term) ->
throw(error(domain_error(category_property, Term), Context))
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(var_or_protocol_property, Term, Context) :-
( var(Term) ->
true
; '$lgt_valid_protocol_property'(Term) ->
true
; callable(Term) ->
throw(error(domain_error(protocol_property, Term), Context))
; throw(error(type_error(callable, Term), Context))
).
'$lgt_check'(flag, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; '$lgt_valid_flag'(Term) ->
true
; '$lgt_user_defined_flag_'(Term, _, _) ->
true
; atom(Term) ->
throw(error(domain_error(flag, Term), Context))
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(var_or_flag, Term, Context) :-
( var(Term) ->
true
; '$lgt_valid_flag'(Term) ->
true
; '$lgt_user_defined_flag_'(Term, _, _) ->
true
; atom(Term) ->
throw(error(domain_error(flag, Term), Context))
; throw(error(type_error(atom, Term), Context))
).
'$lgt_check'(read_write_flag, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; \+ atom(Term) ->
throw(error(type_error(atom, Term), Context))
; \+ '$lgt_valid_flag'(Term),
\+ '$lgt_user_defined_flag_'(Term, _, _) ->
throw(error(domain_error(flag, Term), Context))
; '$lgt_read_only_flag'(Term) ->
throw(error(permission_error(modify, flag, Term), Context))
; '$lgt_user_defined_flag_'(Term, read_only, _) ->
throw(error(permission_error(modify, flag, Term), Context))
; true
).
'$lgt_check'(var_or_read_write_flag, Term, Context) :-
( var(Term) ->
true
; \+ atom(Term) ->
throw(error(type_error(atom, Term), Context))
; \+ '$lgt_valid_flag'(Term),
\+ '$lgt_user_defined_flag_'(Term, _, _) ->
throw(error(domain_error(flag, Term), Context))
; '$lgt_read_only_flag'(Term) ->
throw(error(permission_error(modify, flag, Term), Context))
; '$lgt_user_defined_flag_'(Term, read_only, _) ->
throw(error(permission_error(modify, flag, Term), Context))
; true
).
'$lgt_check'(flag_value, Term1+Term2, Context) :-
( var(Term2) ->
throw(error(instantiation_error, Context))
; '$lgt_valid_flag_value'(Term1, Term2) ->
true
; '$lgt_user_defined_flag_'(Term1, _, Type),
call(Type, Term2) ->
true
; throw(error(domain_error(flag_value, Term1 + Term2), Context))
).
'$lgt_check'(var_or_flag_value, Term1+Term2, Context) :-
( var(Term2) ->
true
; '$lgt_valid_flag_value'(Term1, Term2) ->
true
; '$lgt_user_defined_flag_'(Term1, _, Type),
call(Type, Term2) ->
true
; throw(error(domain_error(flag_value, Term1 + Term2), Context))
).
'$lgt_check'(predicate_property, Term, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; '$lgt_valid_predicate_property'(Term) ->
true
; '$lgt_prolog_predicate_property'(Term) ->
true
; throw(error(domain_error(predicate_property, Term), Context))
).
'$lgt_check'(var_or_predicate_property, Term, Context) :-
( var(Term) ->
true
; '$lgt_valid_predicate_property'(Term) ->
true
; '$lgt_prolog_predicate_property'(Term) ->
true
; throw(error(domain_error(predicate_property, Term), Context))
).
'$lgt_check'(key_value_info_pair, Term, Context) :-
( Term = (Key is Value) ->
'$lgt_check'(atom, Key, Context),
'$lgt_check'(nonvar, Value, Context)
; throw(error(type_error(key_value_info_pair, Term), Context))
).
'$lgt_check_list'(Type, Term, Original, Context) :-
( var(Term) ->
throw(error(instantiation_error, Context))
; Term == [] ->
true
; Term = [_| Tail] ->
'$lgt_check_list'(Type, Tail, Original, Context)
; throw(error(type_error(Type, Original), Context))
).
% '$lgt_check'(+atom, @term)
%
% this simpler version of the predicate is mainly used when compiling source files
'$lgt_check'(Type, Term) :-
catch('$lgt_check'(Type, Term, _), error(Error, _), throw(Error)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Logtalk startup initialization
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% dynamic entity counters initial definitions
%
% counters used when generating identifiers for dynamically created entities
'$lgt_dynamic_entity_counter_'(object, o, 1).
'$lgt_dynamic_entity_counter_'(protocol, p, 1).
'$lgt_dynamic_entity_counter_'(category, c, 1).
% '$lgt_load_built_in_entities'(-atom)
%
% loads all built-in entities if not already loaded (when embedding
% Logtalk, the pre-compiled entities are loaded prior to this file)
'$lgt_load_built_in_entities'(ScratchDirectory) :-
( '$lgt_expand_library_alias'(scratch_directory, ScratchDirectory) ->
% user override for the default scratch directory
'$lgt_set_compiler_flag'(scratch_directory, ScratchDirectory)
; % use default scratch directory
'$lgt_expand_library_alias'(logtalk_user, LogtalkUserDirectory),
atom_concat(LogtalkUserDirectory, 'scratch/', ScratchDirectory)
),
'$lgt_load_built_in_entity'(expanding, protocol, 'expanding', ScratchDirectory),
'$lgt_load_built_in_entity'(monitoring, protocol, 'monitoring', ScratchDirectory),
'$lgt_load_built_in_entity'(forwarding, protocol, 'forwarding', ScratchDirectory),
'$lgt_load_built_in_entity'(user, object, 'user', ScratchDirectory),
'$lgt_load_built_in_entity'(logtalk, object, 'logtalk', ScratchDirectory),
'$lgt_load_built_in_entity'(core_messages, category, 'core_messages', ScratchDirectory),
% remember that all built-in entities are loaded and thus tokenization for
% compiler and runtime error and warning messages is available
assertz('$lgt_built_in_entities_loaded_').
'$lgt_load_built_in_entity'(Entity, Type, File, ScratchDirectory) :-
( Type == protocol,
'$lgt_current_protocol_'(Entity, _, _, _, _) ->
true
; Type == category,
'$lgt_current_category_'(Entity, _, _, _, _, _) ->
true
; Type == object,
'$lgt_current_object_'(Entity, _, _, _, _, _, _, _, _, _, _) ->
true
; % not an embedded entity; compile and load it
logtalk_load(
core(File),
[ % we need a fixed code prefix as some of the entity predicates may need
% to be called directly by the compiler/runtime
code_prefix('$'),
% delete the generated intermediate files as they may be non-portable
% between backend Prolog compilers
clean(on),
% use a scratch directory where we expect to have writing permission
scratch_directory(ScratchDirectory),
% optimize entity code, allowing static binding to this entity resources
optimize(on),
% don't print any messages on the compilation and loading of these entities
report(off),
% prevent any attempts of logtalk_make(all) to reload this file
reload(skip)
]
)
).
% '$lgt_load_settings_file'(+atom, -callable)
%
% loads any settings file defined by the user; settings files are compiled
% and loaded silently, ignoring any errors; the intermediate Prolog files
% are deleted using the clean/1 compiler flag in order to prevent problems
% when switching between backend Prolog compilers; returns the result from
% the loading attempt for printing after banner and default flags
'$lgt_load_settings_file'(ScratchDirectory, Result) :-
'$lgt_default_flag'(settings_file, Value),
Options = [
% delete the generated intermediate file as it may be non-portable
% between backend Prolog compilers
clean(on),
% use a scratch directory where we expect to have writing permission
scratch_directory(ScratchDirectory),
% optimize any entity code present, allowing static binding to
% entity resources, and preventing their redefinition
optimize(on), reload(skip),
% don't print any compilation or loading messages
report(off)
],
'$lgt_load_settings_file'(Value, Options, Result).
'$lgt_load_settings_file'(deny, _, disabled).
'$lgt_load_settings_file'(restrict, Options, Result) :-
( '$lgt_settings_file_search_directory'(restrict, Directory),
'$lgt_load_settings_file_from_directory'(Directory, Options, Result) ->
true
; % no settings file found
Result = none(restrict)
).
'$lgt_load_settings_file'(allow, Options, Result) :-
( '$lgt_settings_file_search_directory'(allow, Directory),
'$lgt_load_settings_file_from_directory'(Directory, Options, Result) ->
true
; % no settings file found
Result = none(allow)
).
'$lgt_settings_file_search_directory'(allow, Directory) :-
'$lgt_expand_library_alias'(startup, Directory).
'$lgt_settings_file_search_directory'(allow, Directory) :-
'$lgt_settings_file_search_directory'(restrict, Directory).
'$lgt_settings_file_search_directory'(restrict, Directory) :-
'$lgt_expand_library_alias'(logtalk_user, Directory).
'$lgt_settings_file_search_directory'(restrict, Directory) :-
'$lgt_expand_library_alias'(home, Directory).
'$lgt_settings_file_search_directory'(restrict, Directory) :-
'$lgt_environment_variable'('COMSPEC', _),
% Windows systems define this environment variable but not POSIX systems
'$lgt_environment_variable'('APPDATA', APPDATA),
atom_concat(APPDATA, '\\Logtalk\\', Directory).
'$lgt_settings_file_search_directory'(restrict, Directory) :-
'$lgt_environment_variable'('XDG_CONFIG_HOME', XDG_CONFIG_HOME),
atom_concat(XDG_CONFIG_HOME, '/logtalk/', Directory).
'$lgt_settings_file_search_directory'(restrict, Directory) :-
'$lgt_expand_library_alias'(home, Home),
atom_concat(Home, '.config/logtalk/', Directory).
'$lgt_load_settings_file_from_directory'(Directory, Options, Result) :-
( '$lgt_file_extension'(logtalk, Extension),
% more than one possible extension may be listed in the used adapter file
atom_concat(settings, Extension, SettingsFile),
% construct full path to the possible settings file; directories resulting
% from library alias expansion are guaranteed to end with a slash
atom_concat(Directory, SettingsFile, SettingsPath),
'$lgt_file_exists'(SettingsPath) ->
% settings file found; compile and load it
( catch(logtalk_load(SettingsPath, Options), _, fail) ->
Result = loaded(Directory)
; Result = error(Directory)
)
; % no settings file in this directory
fail
).
% '$lgt_report_settings_file'(@nonvar)
%
% reports result of the attempt to load a settings file defined by the user
'$lgt_report_settings_file'(loaded(Path)) :-
'$lgt_print_message'(comment(settings), loaded_settings_file(Path)).
'$lgt_report_settings_file'(disabled) :-
'$lgt_print_message'(comment(settings), settings_file_disabled).
'$lgt_report_settings_file'(error(Path)) :-
'$lgt_print_message'(error, error_loading_settings_file(Path)).
'$lgt_report_settings_file'(none(Flag)) :-
'$lgt_print_message'(comment(settings), no_settings_file_found(Flag)).
% cache default and read-only compiler flags to improve the performance
% of the compiler by reducing the potential number of flag levels that
% need to be checked for finding the value of a flag in a given context
%
% although there should be no clauses for the '$lgt_current_flag_'/2
% predicate when this predicate is called at runtime initialization, a
% wrong file order when embedding Logtalk or a Logtalk application can
% falsify this assumption; therefore, we test for a flag definition
% before caching its default value
'$lgt_cache_compiler_flags' :-
'$lgt_default_flag'(Name, Value),
\+ '$lgt_current_flag_'(Name, _),
assertz('$lgt_current_flag_'(Name, Value)),
fail.
'$lgt_cache_compiler_flags' :-
'$lgt_prolog_feature'(Name, Value),
\+ '$lgt_current_flag_'(Name, _),
assertz('$lgt_current_flag_'(Name, Value)),
fail.
'$lgt_cache_compiler_flags' :-
'$lgt_version_data'(VersionData),
assertz('$lgt_current_flag_'(version_data, VersionData)).
% '$lgt_compile_default_hooks'
%
% compiles the default hooks specified on the backend adapter file or
% settings file for better performance when compiling source files
'$lgt_compile_default_hooks' :-
( '$lgt_compiler_flag'(hook, Hook) ->
'$lgt_compile_hooks'(Hook)
; true
).
% '$lgt_start_runtime_threading'
%
% initializes the engines mutex plus the asynchronous threaded calls mutex
% and tag counter support for backends supporting multi-threading programming
% (currently we use integers for the tag counter, which impose a limitation on
% the maximum number of tags on backends with bounded integers)
'$lgt_start_runtime_threading' :-
( '$lgt_prolog_feature'(engines, supported) ->
mutex_create(_, [alias('$lgt_engines')]),
( current_prolog_flag(bounded, true) ->
current_prolog_flag(min_integer, Min),
assertz('$lgt_threaded_engine_tag_counter_'(Min))
; assertz('$lgt_threaded_engine_tag_counter_'(0))
)
; true
),
( '$lgt_prolog_feature'(threads, supported) ->
mutex_create(_, [alias('$lgt_threaded_tag')]),
( current_prolog_flag(bounded, true) ->
current_prolog_flag(min_integer, Min),
assertz('$lgt_threaded_tag_counter_'(Min))
; assertz('$lgt_threaded_tag_counter_'(0))
)
; true
).
% '$lgt_check_prolog_version'
%
% checks for a compatible backend Prolog compiler version
%
% note, however, that an old and incompatible backend Prolog version may
% break Logtalk initialization before this checking predicate is called
'$lgt_check_prolog_version' :-
'$lgt_prolog_feature'(prolog_version, Current),
'$lgt_prolog_feature'(prolog_compatible_version, Check),
functor(Check, Operator, 1),
arg(1, Check, Compatible),
( call(Operator, Current, Compatible) ->
true
; '$lgt_print_message'(
warning(compatibility),
possibly_incompatible_prolog_version(Current, Compatible)
)
).
% Logtalk runtime initialization
%
% when embedding Logtalk in a saved state created by a backend Prolog
% compiler, the runtime initialization may be triggered again when
% running the saved state; we use a dynamic predicate as a flag to
% prevent redoing this initialization
%
% we write the initialization/1 directive at the end of the file to
% avoid issues with backend Prolog compilers that fail to fully support
% ISO Prolog specified semantics for this directive
'$lgt_runtime_initialization' :-
'$lgt_runtime_initialization_completed_',
!.
'$lgt_runtime_initialization' :-
'$lgt_cache_compiler_flags',
'$lgt_load_built_in_entities'(ScratchDirectory),
'$lgt_load_settings_file'(ScratchDirectory, Result),
'$lgt_print_message'(banner, banner),
'$lgt_print_message'(comment(settings), default_flags),
'$lgt_compile_default_hooks',
'$lgt_start_runtime_threading',
'$lgt_report_settings_file'(Result),
'$lgt_print_message'(comment(help), help),
'$lgt_check_prolog_version',
assertz('$lgt_runtime_initialization_completed_').
:- initialization('$lgt_runtime_initialization').
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% end!
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%