% Search a OO database: % -------------------- :- dynamic( limit_count/1 ). :- dynamic( limit/1 ). % pre-loading of namespaces % [load the namespaces in turn while queries are not being executed] do_load_all_namespaces( List, X, Thread ) :- fork( load_and_prime_namespaces( List, X ), Thread ). load_and_prime_namespaces( List, X ) :- load_namespaces( List, X ), prime_namespaces( List, X ). load_namespaces( [], X ) :- !. load_namespaces( [H|T], X ) :- ( load_namespace( H, X ) -> true; true ), load_namespaces( T, X ). load_namespace( H, X ) :- lock( X ), atom_chars( H, AtomChars ), atom_chars( '_database', EndChars ), append( AtomChars, EndChars, AssName ), atom_chars( AssemblyName, AssName ), ( load_assembly( AssemblyName ) -> true; true ), write( 'Loaded: ' ), write( AssemblyName ), nl, unlock( X ). prime_namespaces( [], X ) :- !. prime_namespaces( [H|T], X ) :- ( prime_namespace( H, X ) -> true; true ), prime_namespaces( T, X ). prime_namespace( H, X ) :- lock( X ), write( 'priming...' ), nl, atom_chars( H, AtomChars ), atom_chars( '_database', EndChars ), append( AtomChars, EndChars, AssName ), atom_chars( AssemblyName, AssName ), ( load_assembly( AssemblyName ) -> true; true ), oo_search_class_defines_prime( H, ['x'] ), write( 'Primed: ' ), write( H ), nl, unlock( X ). % main entry % ---------- echo_input( [] ) :- !. echo_input( [H|T] ) :- write( H ), nl, echo_input( T ). reverse(List, Reversed) :- reverse(List, [], Reversed). reverse([], Reversed, Reversed). reverse([Head|Tail], SoFar, Reversed) :- reverse(Tail, [Head|SoFar], Reversed). % oo_search_namespaces( , , , ). % this should find the lists for every member of and % append these lists together to form the % each namespace in the list is an atom of the form 'System', and this would load % the DLL System_database.dll oo_search_namespaces( Namespaces, Type, Classes, Static, Input, X, Limit, LOCK, Thread ) :- global_abolish( limit_count/1 ), global_abolish( limit/1 ), global_assert( limit_count( 0 ) ), global_assert( limit( Limit ) ), reverse( Namespaces, NamespacesR ), reverse( Input, InputR ), fork( oo_search_namespaces_lock( NamespacesR, Type, Classes, Static, InputR, X, LOCK ), Thread ). oo_search_namespaces_lock( A, B, C, D, E, F, LOCK ) :- lock( LOCK ), oo_search_namespaces_inner( A, B, C, D, E, F ), unlock( LOCK ). oo_search_namespaces_inner( [], _, _, _, _, X ) :- !, pulse( X, 0 ). oo_search_namespaces_inner( [H|T], Type, Classes, Static, Input, X ) :- atom_chars( H, AtomChars ), atom_chars( '_database', EndChars ), append( AtomChars, EndChars, AssName ), atom_chars( AssemblyName, AssName ), load_assembly( AssemblyName ), % echo_input( Input ), oo_search_iterate_classes( H, Type, Classes, Static, Input, X ), ( reached_end -> pulse( X, 0 ) ; oo_search_namespaces_inner( T, Type, Classes, Static, Input, X ) ). oo_search_iterate_classes( H, Type, [], either, Input, X ) :- !, once( oo_search( H, _, _, Type, Input, X ) ). oo_search_iterate_classes( H, Type, [], Static, Input, X ) :- !, once( oo_search( H, _, Static, Type, Input, X ) ). oo_search_iterate_classes( H, Type, List, either, Input, X ) :- !, once( oo_search_iterate_classes_inner( H, Type, List, _, Input, X ) ). oo_search_iterate_classes( H, Type, List, Static, Input, X ) :- once( oo_search_iterate_classes_inner( H, Type, List, Static, Input, X ) ). oo_search_iterate_classes_inner( _, _, [], _, _, _ ) :- !. oo_search_iterate_classes_inner( H, Type, [ClassHead|ClassTail], Static, Input, X ) :- oo_search( H, ClassHead, Static, Type, Input, X ), oo_search_iterate_classes_inner( H, Type, ClassTail, Static, Input, X ). append( [], L, L ). append( [H1|T1], L2, [H1|L3] ) :- append( T1, L2, L3 ). % indirection. % ------------ oo_search( N, Class, Static, meth_args, Args, List ) :- oo_search_meth_args( N, Class, Static, Args, List ). oo_search( N, Class, Static, meth_exact_args, Args, List ) :- oo_search_meth_exact_args( N, Class, Static, Args, List ). oo_search( N, Class, Static, meth_exact_ordered_args, Args, List ) :- oo_search_meth_exact_ordered_args( N, Class, Static, Args, List ). oo_search( N, Class, Static, meth_return, RetType, List ) :- oo_search_meth_return( N, Class, Static, RetType, List ). oo_search( N, Class, Static, field_type, Type, List ) :- oo_search_field_type( N, Class, Static, Type, List ). oo_search( N, Class, Static, class_defines, Member, List ) :- oo_search_class_defines( N, Member, List ). oo_search( N, Class, Static, class_superclass, ClassInput, List ) :- oo_search_class_superclass( ClassInput, List ). oo_search( N, Class, Static, class_direct_subclasses, ClassInput, List ) :- oo_search_class_direct_subclasses( ClassInput, List ). % classes and interfaces are both members % --------------------------------------- members( A, B, C, D, E ) :- call( classmember( A, B, C, D, E ) ). members( A, B, C, D, E ) :- call( interfacemember( A, B, C, D, E ) ). members( A, B, C, D, E ) :- call( structmember( A, B, C, D, E ) ). % pulse % ----- pulse( X, N ) :- X = N, inc_count, fail. pulse( _, _ ). inc_count :- global_call( limit_count( C ) ), C1 is C + 1, global_retract( limit_count( C ) ), global_assert( limit_count( C1 ) ), write( 'Limit count is : ' ), write( C1 ), nl. reached_end :- global_call( limit( L ) ), global_call( limit_count( C ) ), C == L. not_reached_end :- global_call( limit( L ) ), global_call( limit_count( C ) ), C =\= L. % method args % ----------- oo_search_meth_args( N, Class, Static, Args, X ) :- meth_args( N, Class, Static, Args, Result ), pulse( X, Result ), reached_end, !. oo_search_meth_args( _, _, _, _, _ ). meth_args( N, C, Static, Args, class_method( C, M, Args2, Static ) ) :- members( N, C, Static, method, MArgs ), MArgs =.. [ M |[ RetType | Args2 ] ], once( list_subset( Args, Args2 ) ). list_subset( [X|Xs], Ys ) :- select( X, Ys, Zs ), list_subset( Xs, Zs ). list_subset( [], _ ). select( H, [H|T], T ). select( X, [H|T], [H|L] ) :- select( X, T, L ). append( [], L2, L2 ). append( [H1|T1], L2, [H1|L3] ) :- append( T1, L2, L3 ). % method exact args % ----------------- oo_search_meth_exact_args( N, Class, Static, Args, X ):- meth_exact_args( N, Class, Static, Args, Result ), pulse( X, Result ), reached_end, !. oo_search_meth_exact_args( _, _, _, _, _ ). meth_exact_args( N, C, Static, Args, class_method( C, M, Args2, Static ) ) :- members( N, C, Static, method, MArgs ), MArgs =.. [ M |[ RetType | Args2 ] ], list_perm( Args, Args2 ). list_perm( [], [] ). list_perm(List, [First|Perm]) :- select(First, List, Rest), list_perm(Rest, Perm). % method exact ordered args % ------------------------- oo_search_meth_exact_ordered_args( N, Class, Static, Args, X ) :- meth_exact_ordered_args( N, Class, Static, Args, Result ), pulse( X, Result ), reached_end, !. oo_search_meth_exact_ordered_args( _, _, _, _, _ ). meth_exact_ordered_args( N, C, Static, Args, class_method( C, M, Args2, Static ) ) :- members( N, C, Static, method, MArgs ), MArgs =.. [ M |[ RetType | Args2 ] ], list_equal( Args, Args2 ). list_equal( [], [] ). list_equal( [H|T1], [H|T2] ) :- list_equal( T1, T2 ). % search for method which returns given type % ------------------------------------------ oo_search_meth_return( N, Class, Static, [RetType], X ) :- meth_return( N, Class, Static, RetType, Result ), pulse( X, Result ), reached_end, !. oo_search_meth_return( _, _, _, _, _ ). meth_return( N, C, Static, RetType, class_method( C, M, Args, Static ) ) :- members( N, C, Static, method, MArgs ), MArgs =.. [M | [ RetType | Args ] ]. % search for field by type % ------------------------ oo_search_field_type( N, Class, Static, [Type], X ) :- field_type( N, Class, Static, Type, Result ), pulse( X, Result ), reached_end, !. oo_search_field_type( _, _, _, _, _ ). field_type( N, C, Static, Type, class_field( C, F, Static ) ) :- members( N, C, Static, field, FType ), FType =.. [ F, Type ]. % search for a class which defines a given member name % ---------------------------------------------------- oo_search_class_defines( N, [Member], X ) :- class_defines( N, Member, Result ), pulse( X, Result ), reached_end, !. oo_search_class_defines( _, _, _ ). class_defines( N, Member, class( Class ) ) :- members( N, Class, _, _, M ), M =.. [ Member | _ ]. % priming version of the above % ---------------------------- oo_search_class_defines_prime( N, [Member] ) :- class_defines( N, Member, _ ), fail. oo_search_class_defines_prime( _, _ ). % find all superclasses starting with the direct one % -------------------------------------------------- oo_search_class_superclass( [Class], X ) :- pulse( X, class( Class ) ), iterate_up_hierachy( Class, X ). iterate_up_hierachy( Class, X ) :- call( derives( Superclass, Class ) ), pulse( X, class( Superclass ) ), not_reached_end, !, iterate_up_hierachy( Superclass, X ). iterate_up_hierachy( _, _ ). % direct subclasses % ----------------- oo_search_class_direct_subclasses( [Class], X ) :- class_superclass( Result, Class ), pulse( X, class( Result ) ), reached_end, !. oo_search_class_direct_subclasses( _, _ ). class_superclass( Subclass, Class ) :- call( derives( Class, Subclass ) ).