1/*****************************************************************************
    2 * This file is part of the Prolog Development Tool (PDT)
    3 * 
    4 * Author: Tobias Rho
    5 * WWW: http://sewiki.iai.uni-bonn.de/research/pdt/start
    6 * Mail: pdt@lists.iai.uni-bonn.de
    7 * Copyright (C): 2013, CS Dept. III, University of Bonn
    8 * 
    9 * All rights reserved. This program is  made available under the terms
   10 * of the Eclipse Public License v1.0 which accompanies this distribution,
   11 * and is available at http://www.eclipse.org/legal/epl-v10.html
   12 * 
   13 ****************************************************************************/
   14
   15/*
   16 * Structure of the file:
   17 *
   18 * - conditions used by CTs
   19 * - actions    used by CTs
   20 * - dynamic predicates
   21 * - auxiliary predicates
   22 *
   23 * Author:      Tobias Rho
   24 * Date:        30.08.02
   25 * Last Change: 13.09.05
   26 */
   27
   28/* *** PUBLIC API **********************************************/
   29
   30/* *** CONDITIONS **********************************************
   31 *
   32 * Predicates used in the CT conditions generation.
   33 * These predicates are marked with CONDITION 
   34 * in the documentation.
   35 *
   36 */
   37cond(matchParams(_ParametersOrArgs, _PatternList)).
   38cond(extract_class_name(_FQN,_PackageName, _ClassName)).
   39
   40/* *** ACTIONS *************************************************
   41 *
   42 * Documentation copied from JTEngine/api/high_level_api.pl:
   43 *
   44 * Every predicate in the post action part of a
   45 * CT must be tagged with action/1.
   46 * Otherwise ct_apply/1 will throw an exception.
   47 * This design was choosen to be able to give actions
   48 * simple names which are be mapped to full names
   49 * when applied. Ambiguities with Prolog build-ins are avoided.
   50 */
   51
   52action( before(JP, Statements,ForwMethod,ForwBody)) :-              before(JP, Statements,ForwMethod,ForwBody), !.
   53action( after(JP, Statements,ForwMethod,ForwBody)) :-               after(JP, Statements,ForwMethod,ForwBody), !.
   54action( around(JoinPoint, _aroundStmts,_forwMethod,_forwBody)):-    around(JoinPoint,_aroundStmts,_forwMethod,_forwBody).
   55
   56action( add_unboxing_return(_return, _parent, _encl, _expr)):-      add_unboxing_return(_return, _parent, _encl, _expr).
   57%action( add_advice_param_ref(_pc,_adviceParam,_id,_parent,_encl)):- add_advice_param_ref(_pc,_adviceParam,_id,_parent,_encl).
   58%malte
   59%action( add_proceed_call(_pc,_call,_parent, _enclMethod,_adviceArgs,_proceedArgs)):-add_proceed_call(_pc,_call, _parent, _enclMethod,_adviceArgs,_proceedArgs).
   60action(add_advice_instance_method_parameters(AdviceInstanceMethod, JP, AdviceParametersAndKinds,Parameters)) :-
   61add_advice_instance_method_parameters(AdviceInstanceMethod, JP, AdviceParametersAndKinds,Parameters).
   62
   63action(join_point_exceptions(JP,Exception)):-join_point_exceptions(JP,Exception).
   64action( concat_lists(A,B)):-    concat_lists(A,B).
   65action( addArgList(FnArgs, PcArgs, Idents, Parent, ForwMethod)):-   addArgList(FnArgs, PcArgs, Idents, Parent, ForwMethod).
   66action( addArg(FnArg,PcArgs,Ident,Parent,ForwMethod)):-             addArg(FnArg,PcArgs,Ident,Parent,ForwMethod).	    
   67action( addParamList(Params, Ids,Parent)) :-                        addParamList(Params, Ids,Parent).
   68action( addParamReferenceList(Refs, Params, Parent,Encl)) :-        addParamReferenceList(Refs, Params, Parent,Encl).
   69action( add_to_class_fq(Class,Member)):-             				add_to_class_fq(Class,Member).
   70action( copy_method_body(Method,BodyToCopy,Body)) :-                copy_method_body(Method,BodyToCopy,Body).
   71action( showError(Kind,ID,Msg)):-                                   showError(Kind,ID,Msg).
   72
   73
   74    
   75
   76
   77/*
   78 * addArgList(FnArgs, PcArgs, Ids, Parent, ForwMethod)
   79 * 
   80 * ACTION
   81 *
   82 * Recursive implementation of addArg/5, first parameter is a list
   83 * insead of on argument.
   84 * see addArg/5 documentation
   85 * for details.
   86 *
   87 */    
   88addArgList([], _, [], _,_).
   89addArgList([FnArg|FnArgs], PcArgs, [Ident|Idents], Parent, ForwMethod) :-
   90    addArg(FnArg,PcArgs,Ident,Parent,ForwMethod),
   91    addArgList(FnArgs, PcArgs, Idents, Parent, ForwMethod).
   92
   93/*
   94 * addArg(+FnArg,+JpArgs,+Ident,+Parent,+ForwMethod)
   95 * 
   96 * ACTION
   97 *
   98 * adds a reference (identT) to an advice parameter.
   99 * Parameters:
  100 *   FnArgs: The selected advice parameter
  101 *   JpArgs: The arguments at the join point (including target and this)
  102 *   Ident:  The new Id
  103 *   Parent: The parent of the Id
  104 *   ForwMethod: The enclosing forwarding method
  105 * 
  106 */    
  107 
  108addArg(FnArg,PcArgs,Ident,Parent,ForwMethod):-
  109    methodT(ForwMethod,_,_,[_This,_Target|ArgParams],_,_,_),
  110    lookupForwParameter(ForwMethod, FnArg,PcArgs,ArgParams,Param, Name),
  111    add(identT(Ident,Parent,ForwMethod,Name,Param)).
  112
  113/*
  114 * add_advice_instance_method_parameters(+AdviceInstanceMethod, +JP, +AdviceParametersAndKinds,ThisType, TargetType, Parameters)
  115 *
  116 * @param AdviceParametersAndKinds [(Param, Kind),...] : Kind = target, this, argument id at join point
  117 */
  118 add_advice_instance_method_parameters(AdviceInstanceMethod, JP, AdviceParametersAndKinds,
  119                                     [ThisParam,TargetParam|ArgParameters]) :-
  120    %get_join_point_arguments(JP, Args), 
  121    local_vars_of_jp(JP, ArgsTemp),
  122    lvar_ids(ArgsTemp,Args2),
  123
  124    getReceiverTypeOrEnclosingIfInAnonymousClass_fq(JP,Type),    
  125  	enclClass(JP, EnclClass),
  126  	(
  127  	anonymousClass(EnclClass) ->
  128  		(
  129  		classT(EnclClass,Parent,_,_),
  130	  	identT(_,Parent,_,_,EnclClassTmp),
  131  		fullQualifiedName(EnclClassTmp,ClassName)
  132  		);
  133  		enclClass_fq(JP,ClassName)
  134  	),  		
  135    get_or_add_parameter(AdviceInstanceMethod,this,AdviceParametersAndKinds, ClassName, ThisParam),
  136    get_or_add_parameter(AdviceInstanceMethod,target,AdviceParametersAndKinds, Type, TargetParam),    
  137    get_or_add_parameter_if_afterThrowingOrReturning_param_exists(	AdviceParametersAndKinds,AfterParam),    
  138    get_or_add_argument_parameters(AdviceInstanceMethod, Args, -1, AdviceParametersAndKinds, CurrentArgParameters),
  139    (
  140    	nonvar(AfterParam)->
  141    		concat_lists([AfterParam,CurrentArgParameters,Args2],ArgParameters) ;
  142    		concat_lists([CurrentArgParameters,Args2],ArgParameters)
  143    ).
  144    
  145
  146/*
  147 *
  148 */
  149get_or_add_argument_parameters(_, [],_, _, []).
  150
  151get_or_add_argument_parameters(AdviceInstanceMethod, [Arg|Args], Num, 
  152                               AdviceParametersAndKinds, [ArgParameter|ArgParameters]) :-
  153    plus(Num, 1, Next),
  154    Arg = lvar(Argument,_),
  155	get_or_add_argument_parameter(AdviceInstanceMethod, Argument, Next, AdviceParametersAndKinds, ArgParameter),
  156	get_or_add_argument_parameters(AdviceInstanceMethod, Args, Next, AdviceParametersAndKinds, ArgParameters).
  157
  158    get_or_add_argument_parameter(_, Argument, _,AdviceParametersAndKinds, ArgParameter):-
  159    memberchk((ArgParameter, Argument),AdviceParametersAndKinds),
  160    !.
  161    
  162
  163%exeption for execution pc
  164get_or_add_argument_parameter(AdviceInstanceMethod, Arg, _Num, _, ArgParameter):-    
  165  	aopT(JP,_,AdviceInstanceMethod),
  166   	methodT(JP,_,_,_,_,_,_),
  167    new_id(ArgParameter),       
  168    paramT(Arg,  _, _, ArgName)    ,
  169    getType(Arg,Type),
  170  	add(paramT(ArgParameter,  AdviceInstanceMethod, Type, ArgName)).
  171    	 
  172    	 
  173get_or_add_argument_parameter(AdviceInstanceMethod, Arg, Num, _, ArgParameter):-
  174    new_id(ArgParameter),
  175    getType(Arg,Type),
  176    get_arg_name(Arg,Num, ArgName),
  177    add(paramT(ArgParameter,  AdviceInstanceMethod, Type, ArgName)). 
  178 
  179
  180
  181get_arg_name(ArgID,Num,ArgName):-    
  182    paramT(ArgID,  _, _, ArgName);
  183    atom_concat('_arg', Num, ArgName).
  184
  185
  186/*
  187  * get_or_add_parameter_if_afterThrowingOrReturning_param_exists(+AdviceParametersAndKinds, -Param)
  188  *
  189  * if the current advice is an afterThrowing oder afterReturning advice, the extra formal will be added to
  190  * the advice method parameters on the thrid position
  191  *
  192  */  
  193  
  194get_or_add_parameter_if_afterThrowingOrReturning_param_exists(AdviceParametersAndKinds, Param) :-
  195    member((Param, extraArg), AdviceParametersAndKinds),
  196    !.
  197
  198get_or_add_parameter_if_afterThrowingOrReturning_param_exists( _, _).
  199
  200 
  201/*
  202 *get_or_add_parameter(_,+Kind,+AdviceParametersAndKinds,_,-Param) :-
  203 */  
  204get_or_add_parameter(_,Kind,AdviceParametersAndKinds,_,Param) :-
  205    member((Param, Kind), AdviceParametersAndKinds),
  206    !.
  207    
  208
  209get_or_add_parameter(AdviceInstanceMethod,'target', _, TargetType, Param) :-
  210	createTargetInstanceParam(TargetType, AdviceInstanceMethod, Param),
  211	!.
  212get_or_add_parameter(AdviceInstanceMethod,'this', _, TargetType, Param) :-
  213	createThisInstanceParam(TargetType, AdviceInstanceMethod, Param),
  214	!.
  215
  216/*
  217 * get_join_point_arguments(JP, Args)
  218 *
  219 */
  220 get_join_point_arguments(JP, Args) :-
  221  methodT(JP,_,_,Args,_,_,_),
  222  !.
  223  
  224get_join_point_arguments(JP, Args) :-
  225  methodCall(JP,_,_,_,_,Method,_),
  226  methodT(Method,_,_,Args,_,_,_),
  227  !.
  228get_join_point_arguments(JP, []) :-
  229  getFieldT(JP,_,_,_,_,_),
  230  !.
  231get_join_point_arguments(JP, [Arg]) :-
  232  setField(JP,_,_,_,_,Arg),
  233  !.
  234  
  235 get_join_point_arguments(_, []).  
  236/*
  237  * join_point_exceptions(+JP, -Exceptions)
  238  *
  239  */
  240
  241join_point_exceptions(JP,Exceptions):-
  242  methodT(JP,_,_,_,_,Exceptions,_).
  243  
  244join_point_exceptions(JP,Exceptions):-
  245	methodCall(JP,_,_,_,_,MID,_),
  246	methodT(MID,_,_,_,_,Exceptions,_).
  247 
  248join_point_exceptions(_,[]).
  249
  250
  251
  252
  253/*
  254 * matches_jp_exceptions(+ExceptionFQ,-ExceptionIDs)
  255 *
  256 * TESTED
  257 */
  258matches_exceptions(ExceptionFQ,ExceptionIDs):-    
  259    fullQualifiedNames(ExceptionIDs,ExceptionsFQ),
  260    memberchk(ExceptionFQ,ExceptionsFQ),
  261    !.
  262    
  263matches_exceptions(ExceptionFQ,[Head | Tail]):-    
  264    fullQualifiedName(Head,FQ),  
  265    (
  266    	subtype_name(FQ,ExceptionFQ); 
  267	    matches_exceptions(ExceptionFQ,Tail)
  268	).
  269
  270matches_exceptions(_,[]):- fail.    
  271    
  272
  273    
  274    
  275
  276/*
  277 * getTargetType(+JpID,-RecieverType)
  278 *
  279 *
  280 */
  281getReceiverType(JpID,RecieverType):-       
  282  applyT(JpID,_,_,_,_,_,Member),
  283  enclClass(Member,EnclClass),
  284  getType(EnclClass,RecieverType).
  285
  286getReceiverType(JpID,RecieverType):-           
  287  getFieldT(JpID,_,_,_,_,Member),
  288  enclClass(Member,EnclClass),
  289  getType(EnclClass,RecieverType).
  290      
  291getReceiverType(JpID,RecieverType):-             
  292  setField(JpID,_,_,_,Member,_),    	
  293  enclClass(Member,EnclClass),
  294  getType(EnclClass,RecieverType).
  295    
  296getReceiverType(JpID,RecieverType):-             
  297  methodT(JpID,_,_,_,_,_,_),
  298  enclClass(JpID,EnclClass),
  299  getType(EnclClass,RecieverType).
  300  
  301  
  302/*
  303 * add_unboxing_return(Return, _parent, EnclMethod, _expr)
  304 *
  305 * ACTION
  306 *
  307 * If EnclMethod has the return type void an empty returnT statment
  308 * with the id Return is created.
  309 * 
  310 * Otherwise the unboxingMethod ct is used to create a method 
  311 * in the enclosing class of EnclMethod which unboxes a 
  312 * the corresponding boxing type of PrimitiveType to
  313 * PrimitiveType, e.g. for the basic type int:
  314 *   public int intValue(Integer integer) { return ... }
  315 *
  316 * TESTED
  317 */
  318add_unboxing_return(Return, Parent, EnclMethod, Expr):-
  319    methodT(EnclMethod,_,_, _,type(basic,void,0),_,_),
  320    !,
  321    deleteTree(Expr), 
  322    add(returnT(Return,Parent,EnclMethod,null)).
  323
  324add_unboxing_return(_return, _parent, _encl, _expr):-
  325    enclClass(_encl,_enclClass),
  326    methodT(_encl,_,_, _,type(basic,_primitiveType,0),_,_),
  327    !,
  328    apply_ct(unboxingMethod(_enclClass,_primitiveType)),
  329    atom_concat(_primitiveType, 'Value', _primitiveTypeValue),
  330    methodT(_unboxingMethod, _enclClass,_primitiveTypeValue,[_],type(basic, _primitiveType, 0),[],_),
  331    new_ids([_apply,_select,_ident]),
  332    atom_concat(_primitiveType,'Value',_methodName),
  333    add(returnT(_return,_parent,_encl,_apply)),
  334      add(applyT(_apply,_return,_encl,_ident,_methodName, [_expr],_unboxingMethod)),
  335          add(identT(_ident,_apply,_encl,'this',_enclClass)),
  336    set_parent(_expr,_apply).
  337
  338add_unboxing_return(_return, _parent, _encl, _expr):-
  339    add(returnT(_return,_parent,_encl,_expr)).
  340  
  341%/*
  342% * add_advice_param_ref(JoinPoint,AdviceParam,Id,Parent,EnclMethod)
  343% *
  344% * ACTION
  345% * 
  346% * creates a reference (identT) to the advice 
  347% * parameter "AdviceParam" with the id "Id".
  348% */
  349%
  350%add_advice_param_ref(JP,_adviceParam,_id,_parent,_encl):-
  351%    getForwParam(_pc, _adviceParam, _param,_name),
  352%    add(identT(_id,_parent,_encl,_name,_param)).
  353    
  354    /*
  355 * showError(+Kind, +ID,+Msg)
  356 * 
  357 * ACTION
  358 */
  359showError(_,ID,Msg):-    
  360	var(ID),
  361	write('ID NOT BOUND: '),
  362	write(Msg),
  363	flush_output.
  364
  365showError(Kind, ID,Mesg):-
  366    not(sourceLocation(ID, _,_,_)),
  367    enclMethod(ID,Meth),
  368    method(Meth,Class,Name,_,_,_,_),
  369    fullQualifiedName(Class,Fqn),
  370    format('~w in method ~w.~w: ~w~nCannot find source location: Probably generated by aspect.~n~n',[Kind,Fqn,Name,Mesg]).
  371    
  372
  373showError(Kind,ID,Msg):-    
  374    enclMethod(ID,Meth),
  375    method(Meth,Class,Name,_,_,_,_),
  376    fullQualifiedName(Class,Fqn),
  377    format('~w in method ~w.~w  ',[Kind,Fqn,Name]),
  378    sourceLocation(ID, File,Start,_),
  379    format('(~w:~w)~n~n~w~n', [File,Start,Msg]),
  380    gen_tree(ID),
  381    flush_output,
  382
  383    /*
  384    * Added Dec 20, 2004 to store all errors/warnings
  385    * and move it to the Eclipse Problems View. (AL)
  386    */
  387    assert(isErrorWarningMessage(Kind, ID, Msg)).
  388    
  389    
  390/*
  391 * addParamList(+Params, +Ids,+Parent)
  392 *
  393 * ACTION
  394 */
  395
  396addParamList([],[],_).
  397addParamList([Param|Params], [Id|Ids],Parent) :-
  398    paramT(Param,_,Type,Name),
  399    add(paramT(Id,Parent,Type,Name)),
  400    addParamList(Params, Ids,Parent).    
  401    
  402/*
  403 * addParamReferenceList(+Refs, +Params, +Parent,+Encl)
  404 *
  405 * ACTION
  406 * Adds a list of parameter accesses.
  407 * Parent is the parent id and Encl the 
  408 * enclosing id of the created identT/5 facts.
  409 */
  410addParamReferenceList([], [], _Parent,_Encl).
  411
  412addParamReferenceList([Ref|Refs], [Param|Params], Parent,Encl) :-
  413    paramT(Param,_,_,Name),
  414    add(identT(Ref,Parent,Encl,Name,Param)),
  415	addParamReferenceList(Refs, Params, Parent,Encl).
  416    
  417    
  418    
  419    
  420    
  421/*
  422 * add_to_class_fq(+Class,+Member|+MemberList)
  423 * 
  424 * ACTION
  425 * Adds Member(s) to the class, if the Member is not already in the 
  426 * member list.
  427 * Fails if Class or Member is not bound and if Class is not a
  428 * of type classT.
  429 *
  430 * TESTED
  431 */
  432add_to_class_fq(_, []):- !.
  433add_to_class_fq(Class, [Member|Rest]) :-
  434    add_to_class_fq(Class,Member),
  435    add_to_class_fq(Class,Rest).
  436
  437add_to_class_fq(_class, _id) :-
  438    nonvar(_class),
  439    nonvar(_id),
  440    java_fq(classT(_class, _, _, _members)),
  441    member(_id, _members),
  442    !.
  443    
  444add_to_class_fq(_class, _id) :-
  445    nonvar(_class),
  446    nonvar(_id),
  447    java_fq(classT(_class, _p,_n,_members)),
  448    delete(java_fq(classT(_class, _p,_n,_members))),
  449    append(_members, [_id], _newMembers),
  450    add(java_fq(classT(_class, _p, _n, _newMembers))).
  451 
  452add_to_class_fq(_class, _id) :-
  453    sformat(Msg,'the class ~w could not be found in add_to_class',[_class]),
  454    t_i_based_error_handling(Msg).
  455    
  456
  457/************************** CT CONDITIONS (cond/1) *************************/
  458
  459/*
  460 * bindForwMethod(+JoinPoint,-ForwardingMethod,-Body)
  461 *
  462 * CONDITION
  463 *
  464 * binds forwarding method and body to
  465 * new ids.
  466 * In the case of a execution pointcut
  467 * on the body is bound.
  468 */
  469/*
  470bindForwMethod(_Method,_Method,_Body):-
  471% special case for the execution pointcut
  472    methodT(_Method,_,_,_,_,_,_),
  473    !,
  474    new_id(_Body).
  475
  476bindForwMethod(_,_forwMethod,_forwBody):-
  477    new_ids([_forwMethod,_forwBody]).
  478*/
  479/*
  480 * extract_class_name(+FQN,-Package, -ClassName)
  481 *
  482 * CONDITION
  483 * Atom operation. Binds ClassName to 
  484 * atom part right from most right '.'.
  485 *
  486 * e.g.: class_name('pckg1.pckg2.Class1','pckg1.pckg2','Class1').
  487 *
  488 * TESTED
  489 */
  490
  491extract_class_name(FQN, _PackageName, _ClassName) :-
  492	var(FQN),
  493	throw('INTERNAL ERROR: extract_class_name failed').
  494
  495extract_class_name(FQN, Package, ClassName) :-
  496    extract_class_name_(FQN, FQN, Package, ClassName).
  497	
  498extract_class_name_(FQN, ClassNameTmp, Package, ClassName) :-
  499    concat(_,'.',ClassNameTmp2,ClassNameTmp),
  500    !,
  501    extract_class_name_(FQN, ClassNameTmp2, Package, ClassName).
  502    
  503extract_class_name_(FQN, ClassName, Package,ClassName):-
  504    concat(Package, '.', ClassName, FQN),
  505    !.
  506extract_class_name_(_, ClassName, '',ClassName).   
  507   
  508/*** DYNAMIC PREDICATES ***************************************/
  509
  510:- multifile fieldAccess/2.  511:- multifile action/1.  512
  513/*
  514 * forwarding(Forwarding, LastForwarding,Jp)
  515 * 
  516 * except for the first fact:
  517 * forwarding(Forwarding,Jp,Jp)
  518 */
  519:- dynamic forwarding/3.  520:- dynamic forwarding/1.  521
  522/*
  523 * forwards(LastCall, LastForwarding, Kind, Jp)
  524 *
  525 * LastCall: the call at the real join point
  526 * LastForwarding: the method called by this call
  527 * Kind: getField | setField | execution | methodCall
  528 */
  529:- dynamic forwards/4.  530:- dynamic pointcut/1.  531:- dynamic visibility/3.  532:- dynamic laj_ct_list/1.  533:- multifile laj_ct_list/1.  534:- dynamic laj_binding_transfer/3.  535
  536/*** AUXILIARY PREDICATES ***************************************/
  537  
  538/*
  539 * replaceStatementWithForwarding(JoinPoint) 
  540 *
  541 * see replaceStatementWithForwarding(JoinPoint,ForwMethod,ForwBody).
  542 */
  543 
  544replaceStatementWithForwarding(JP) :-
  545    replaceStatementWithForwarding(JP,_,_).
  546
  547/*
  548 * replaceStatementWithForwarding(JoinPoint,ForwMethod,ForwBody) 
  549 *
  550 * Replaces a Joinpoint execution with the call of a forwarding method.
  551 * 
  552 * If ForwMethod and ForwBody are not bound they are bound to new ids.
  553 * Then, a new forwarding method is created
  554 * 
  555 */
  556
  557replaceStatementWithForwarding(JP,ForwMethod,ForwBody) :-
  558    bindIdIfNeeded(ForwMethod),
  559    bindIdIfNeeded(ForwBody),
  560    (
  561        (forwards(RealJP, _, _,JP),!);
  562        JP = RealJP
  563    ),
  564    enclClass(RealJP, EnclClass),
  565    !,
  566    createForwardingMethod(RealJP, EnclClass,ForwMethod,ForwBody),
  567    add_encl_meth_params(RealJP).
  568
  569/*
  570 * add_encl_meth_params(+Pc) 
  571 */
  572add_encl_meth_params(JP):-
  573    forwards(_,_,execution,JP),
  574    !.
  575    %throw('add_encl_meth_params not allowed for execution').
  576 
  577add_encl_meth_params(JP):-
  578    forwards(_call,LastForwMethod,Kind,JP),
  579    pc_param_num(JP,Kind,PN),
  580    add_encl_params_to_forw_if_need(JP,PN,LastForwMethod).
  581    
  582/*
  583 * add_encl_params_to_forw_if_need(+Pc,+PN,+ForwMethod)
  584 *
  585 * Add parameters of the enclosing method at the
  586 * real pointcut to the forwarding methods.
  587 * This predicate is TODO (X,X equiv. to. X)
  588 */
  589
  590add_encl_params_to_forw_if_need(_,_,ForwMethod):-
  591 	not(methodT(ForwMethod,_,_,_,_,_,_)),
  592 	!.
  593 	
  594 	add_encl_params_to_forw_if_need(_,PN,ForwMethod):-
  595    methodT(ForwMethod,_,_,Params,_,_,_),
  596    length(Params,PN),
  597    !.
  598 	
  599add_encl_params_to_forw_if_need(Pc,PN,ForwMethod):-
  600    methodT(ForwMethod,Class,Name,Params,Type,Exc,Body),
  601	getRealEncl(Pc,ForwMethod,RealEncl),
  602	methodT(RealEncl,_,_,EnclParams,_,_,_),
  603	copy_params(EnclParams,CopiedParams,ForwMethod),
  604	concat_lists([Params,CopiedParams],NewParams),
  605	replace(methodT(ForwMethod,Class,Name,Params,Type,Exc,Body),
  606    	    methodT(ForwMethod,Class,Name,NewParams,Type,Exc,Body)),
  607% replace forwarding call
  608    applyT(Apply,Parent,Encl,Expr,Name,Args,ForwMethod),
  609	
  610    methodT(RealEncl, _,_,RealParams,_,_,_),
  611    length(RealParams,Len),
  612  
  613    create_refs_to_encl_params(Encl,Len,Refs),
  614	concat_lists([Args,Refs],NewArgs),
  615	replace(applyT(Apply,Parent,Encl,Expr,Name,Args,ForwMethod),
  616    	    applyT(Apply,Parent,Encl,Expr,Name,NewArgs,ForwMethod)),
  617    forwarding(ForwMethod,LastForwMethod,Pc),
  618    add_encl_params_to_forw_if_need(Pc,PN,LastForwMethod).
  619
  620
  621/*
  622 * 	copy_params(+EnclParams,?CopiedParams,+ForwMethod)
  623 * 
  624 *  ?f CopiedParams is not bound, new ids will be created for 
  625 *  the new parameters.
  626 */
  627copy_params([],[],_NewEncl).
  628copy_params([Param|Params],[Copy|Copies],NewEncl):-
  629    (var(Copy)-> 
  630       new_id(Copy);true),
  631    paramT(Param,_,Type,Name),
  632    add(paramT(Copy,NewEncl,Type,Name)),
  633    copy_params(Params,Copies,NewEncl).
  634
  635/*
  636 * create_refs_to_encl_params(+Encl,+Len,-Refs)
  637 *
  638 * create idents which reference the Len-length tail 
  639 * of parameters of the method Encl.
  640 */
  641
  642create_refs_to_encl_params(Encl,Len,Refs) :-
  643    methodT(Encl, _,_,Params,_,_,_),
  644    tail(Params,Len,Tail),
  645	create_ref_idents(Tail,Refs).
  646
  647create_ref_idents([],[]).
  648create_ref_idents([Param|Params],[Ref|Refs]):-
  649	paramT(Param,Parent,_,_),
  650	createIdentRefParam(Param,Parent,Ref),
  651	create_ref_idents(Params,Refs).
  652   
  653/*
  654 * pc_param_num(+Pc,+Kind,?PN)
  655 */
  656pc_param_num(_Pc,getField,2).
  657pc_param_num(_Pc,setField,3).
  658pc_param_num(Pc,methodCall,PN) :-
  659    (applyT(Pc,_,_,_,_,Args,_);
  660     newClassT(Pc,_,_,_,Args,_,_,_)),
  661    getRealEncl(Pc,_,RealEncl),
  662    methodT(RealEncl,_,_,Params,_,_,_),
  663    length(Params,ParamsLen),
  664    length(Args,ArgsLen),
  665    plus(2,ArgsLen,Tmp),
  666    plus(Tmp,ParamsLen,PN).
  667
  668pc_param_num(Pc,execution,PN) :-
  669    methodT(Pc,_,_,Args,_,_,_),
  670    length(Args,ArgsLen),
  671    plus(2,ArgsLen,PN).
  672      
  673
  674/*
  675 * Encloses current body with a try finally block and inserts 
  676 * 
  677 * 
  678 Umschlie�e aktuellen Body mit einem try .. finally block und f�ge _insert in den finally Block ein,
  679 * wenn _insert ein Block ist wird insert als finally block eingef�gt.
  680c */
  681
  682addTryFinallyBlockStmts(_,_, []).
  683addTryFinallyBlockStmts(_forwMethod,_finallyBlock, _stmts) :-
  684    addTryFinallyBlock(_forwMethod,_finallyBlock),
  685    prependBlockStatments(_finallyBlock, _stmts).
  686
  687addTryFinallyBlock(_forwMethod,_finallyBlock):-
  688    new_ids([_try, _tryBlock]),
  689    methodT(_forwMethod,_,_,_,_,_,_block),
  690    blockT(_block, _parent, _encl, _stats), % die id des blocks wird dem try zugewiesen
  691    set_parent(_stats, _tryBlock),
  692    delete(blockT(_block, _parent, _encl, _stats)),
  693    add(blockT(_block, _parent,_encl,[_try])),
  694        add(tryT(_try, _block,_encl,_tryBlock, [],_finallyBlock)),
  695            add(blockT(_tryBlock, _try,_encl,_stats)),
  696            add(blockT(_finallyBlock, _try, _encl, [])).
  697
  698/*
  699aroundTryFinallyBlock(_block, _finallyBlock) :-
  700    blockT(_finallyBlock,_,_,_),
  701    !,
  702    new_ids([_try, _tryBlock]),
  703    blockT(_block, _parent, _encl, _stats), % die id des blocks wird dem try zugewiesen
  704    set_parent(_stats, _tryBlock),
  705    retractall(blockT(_block, _,_,_)),
  706    assert(blockT(_block, _parent,_encl,[_try])),
  707        assert(tryT(_try, _block,_encl,_block, [],_finallyBlock)),
  708            assert(blockT(_tryBlock, _try,_encl,_stats)),
  709            set_parent(_finallyBlock, _try),
  710            set_encl_method(_finallyBlock, _encl).
  711
  712aroundTryFinallyBlock(_block, _insert) :-
  713    new_ids([_try, _tryBlock, _finallyBlock]),
  714    blockT(_block, _parent, _encl, _stats), % die id des blocks wird dem try zugewiesen
  715    set_parent(_stats, _tryBlock),
  716    retractall(blockT(_block, _,_,_)),
  717    assert(blockT(_block, _parent,_encl,[_try])),
  718        assert(tryT(_try, _block,_encl,_tryBlock, [],_finallyBlock)),
  719            assert(blockT(_tryBlock, _try,_encl,_stats)),
  720            assert(blockT(_finallyBlock, _try, _encl, [])),
  721%    set_parent(_insert,_finallyBlock),
  722    prependBlockStatment(_finallyBlock, _insert).
  723*/
  724
  725
  726createAdviceMethod(JP,Statements,ForwMethod,ForwBody):-
  727   enclClass(JP,Class),
  728   add(methodT(ForwMethod,Class,'advice',_,_,_,ForwBody)),
  729   add(blockT(ForwBody,ForwMethod,ForwMethod,Statements)).
  730
  731
  732/*
  733 * createThisOrGetReceiver(OldParent, NewParent, Encl, OldReceiver, NewReceiver, DeclaringType) 
  734 */
  735
  736createThisOrGetReceiver(Parent, _newParent, _encl, null, Receiver,DeclaringType) :-
  737%    getFieldT(_ident, Parent, _encl, 'null', _name, _sym),
  738    enclClass(_encl,Anonym),
  739    classT(Anonym,NewClass,_,_),
  740    newClassT(NewClass,_,NewClassEncl,_,_,TypeExpr,_,_),
  741    getType(TypeExpr,type(class, Type,0)),
  742    not(subtype(Type,DeclaringType)),
  743    !,
  744    enclClass(NewClassEncl, Outer),
  745    
  746    (var(Receiver) -> new_id(Receiver);true),
  747    fullQualifiedName(Outer,FQN),
  748    new_id(SelectedTypeExpr),
  749    add(selectT(Receiver,Parent,EnclMethod,'this', SelectedTypeExpr, Outer)),  
  750    add(identT(SelectedTypeExpr, Receiver, EnclMethod, FQN,Outer)).
  751
  752
  753
  754createThisOrGetReceiver(_Parent, NewParent, Encl, null, Receiver,_DeclaringType) :-
  755    !,
  756    enclClass(Encl, EnclClass),
  757    new_id(Receiver),
  758    create_this_or_null_if_static(Receiver,NewParent, Encl, EnclClass).
  759
  760createThisOrGetReceiver(_Parent, NewParent, _encl, Receiver, Receiver,_DeclaringType) :-
  761%createThisOrGetReceiver(GetField, NewParent, Receiver,_DeclaringType) :-
  762    !,
  763    set_parent(Receiver, NewParent).
  764
  765/*
  766 * create_this_or_null_if_static(ID,Parent,EnclMethod,EnclClass)
  767 *
  768 * Will create a reference to this, if EnclMethod is not a static method.
  769 * Otherwise a null ident will be created.
  770 * Will create a new ID, if ID is not bound!
  771 */ 
  772create_this_or_null_if_static(ID, Parent, EnclMethod, _EnclClass):-
  773    modifierT(EnclMethod,'static'),
  774    !,
  775    (var(ID) -> new_id(ID);true),
  776    add(identT(ID, Parent, EnclMethod, 'null', 'null')).
  777
  778create_this_or_null_if_static(ID, Parent, EnclMethod, EnclClass):-
  779    (var(ID) -> new_id(ID);true),
  780    add(identT(ID, Parent, EnclMethod, 'this', EnclClass)).
  784createForwBody(_get, _forwMethod, _forwBody, _ForwName, [_thisParam,_recvParam],/* _Type*/type(basic, void, 0), _execReturn) :-
  785    getFieldT(_get, _parent, _enclMethod, _origReceiver,  _origName, _field),
  786    !,
  787    new_ids([_forwCall, _forwMethIdent]),
  788    fieldT(_field, DeclaringType, _Type, _origName, _),
  789    forwardingMethodName(_get, 'get$', _origName, _ForwName),
  790    enclClass(_enclMethod,_enclClass), %neu
  791    createForwMethParams(_enclClass,_forwMethod,DeclaringType, _origReceiver, [],[_thisParam,_recvParam]),
  792    createIdentRefParam(_recvParam,_callSelect, _forwReceiver),
  793%createThisOrGetReceiver(OldParent, NewParent, Encl, OldReceiver, NewReceiver, DeclaringType)     
  794    createThisOrGetReceiver(_parent, _forwCall, _enclMethod,_origReceiver,_receiver,DeclaringType),
  795    replaceId(_parent, _get, _forwCall),
  796    delete(getFieldT(_get, _parent, _enclMethod, _origReceiver,  _origName, _field)),
  797    create_this_or_null_if_static(_this,_forwCall, _enclMethod, _enclClass), %neu
  798    add(getFieldT(_get, _execReturn, _forwMethod, _forwReceiver, _origName, _field)),
  799    add(applyT(_forwCall, _parent,_enclMethod, 'null', _ForwName, [_this,_receiver],_forwMethod)),
  800    updateForwardsFact(_get,getField,_forwCall,_forwMethod).
  801
  802createForwBody(_set, _forwMethod, _forwBody, _ForwName, [_thisParam,_recvParam,_valueParam],  /*FieldType*/type(basic, void, 0), _execReturn) :-
  803    setField(_set, _parent, _enclMethod, _origReceiver, _field,_value),
  804    !,
  805    new_ids([_forwCall, _forwMethIdent, _selectField,_valueParam]),
  806    assignT(_set, _, _enclMethod, _lhs, _),
  807    fieldT(_field, DeclaringType, _FieldType, _origName, _),
  808    getType(_value,_Type),
  809    forwardingMethodName(_set,'set$', _origName, _ForwName),
  810    enclClass(_enclMethod,_enclClass), %neu
  811    createForwMethParams(_enclClass,_forwMethod,DeclaringType,_origReceiver, [],[_thisParam,_recvParam]),
  812    createIdentRefParam(_recvParam,_callSelect, _forwReceiver),
  813 %createThisOrGetReceiver(OldParent, NewParent, Encl, OldReceiver, NewReceiver, DeclaringType)     
  814    createThisOrGetReceiver(_parent, _forwCall, _enclMethod,_origReceiver,_receiver,DeclaringType),
  815    replaceId(_parent, _set, _forwCall),
  816    set_parent(_value, _forwCall),
  817    deleteTree(_lhs),
  818    add(paramT(_valueParam, _forwMethod, _Type, '_value')),
  819    createIdentRefParam(_valueParam,_set, _forwValue),
  820    create_this_or_null_if_static(_this,_forwCall, _enclMethod, _enclClass), %neu
  821    action(replace(assignT(_set, _execReturn, _forwMethod, _selectField, _forwValue))),
  822      add(getFieldT(_selectField, _set, _forwMethod, _forwReceiver, _origName, _field)),
  823    add(applyT(_forwCall, _parent,_enclMethod, 'null',_ForwName, [_this,_receiver,_value],_forwMethod)),
  824    updateForwardsFact(_set,setField,_forwCall,_forwMethod).
  825
  826createForwBody(_call, _forwMethod, _forwBody, _ForwName, [_thisParam|[_recvParam|_forwParams]], Type, _execReturn) :- %neu
  827    (
  828    	(applyT(_call,_parent,_enclMethod,_expr,_origName,_args, _method_constr),
  829    	 method(_method_constr,_,_,_,Type,_,_));
  830	    (newClassT(_call,_parent,_enclMethod,_method_constr,_args,_,_,_),
  831	    _expr = null,
  832	    constructor(_method_constr,ConstrClass,_,_,_),
  833	    Type = type(class,ConstrClass,0),
  834	     _origName = 'init')
  835	),
  836    !,
  837    debugme,
  838    getOrigArgs(_call,_args,_origArgs),
  839    new_ids([_forwCall, _forwMethIdent]),
  840%    applyT(_call, _parent, _enclMethod, _origReceiver, _),
  841    forwardingMethodName(_call, 'call$',_origName, _ForwName),
  842    enclClass(_enclMethod,_enclClass), %neu
  843    methodT(_method_constr,DeclaringType,_,_,_,_,_),
  844    createForwMethParams(_enclClass,_forwMethod,DeclaringType,_expr,_origArgs,[_thisParam|[_recvParam|_forwParams]]),
  845    replaceId(_parent, _call, _forwCall),
  846    getOrigParams(_call,[_thisParam|[_recvParam|_forwParams]],_origParams),
  847    replaceForwCall(_call, _parent, _method_constr, _origName, _execReturn, _forwMethod,_origParams,_recvParam),
  848    createForwArgs(_call,_enclMethod,_enclClass,_forwCall,_expr,_args,_forwArgs,DeclaringType),
  849    set_parent(_forwArgs,_forwCall),
  850    add(applyT(_forwCall, _parent,_enclMethod, 'null', _ForwName, _forwArgs,_forwMethod)),
  851    updateForwardsFact(_call,methodCall,_forwCall,_forwMethod).
  852
  853% execution
  854createForwMethodExecution(_method, _forwBody,_forwStmts) :- %neu
  855    methodT(_method, _class, _origName, _origParams, _type, _exceptions, _body),
  856    (interfaceT(_class)->
  857    	(fullQualifiedName(_class,FQN),sformat(Msg,'execution pointcut on interfaces not legal in LAJ: ~w',[FQN]),
  858    	 throw(Msg));true
  859    ),	
  860    new_ids([_forwCall, _forwMethIdent,_forwMethod]),
  861
  862%    applyT(_method, _parent, _method, _origReceiver, _),
  863    forwardingMethodName(_method, 'exec$',_origName, _forwName),
  864    enclClass(_method,_class), %neu
  865
  866% ersetzte alte Methode mit neuem Namen
  867    rec_set_encl_method(_body,_forwMethod),
  868    set_parent(_body,_forwMethod),
  869    
  870    cloneParams(_method, _origParams,_newParams),
  871    createThisInstanceParam(_class,_forwMethod,_thisVarDef),   
  872%    createTargetInstanceParam(_class, _forwMethod, 'null',_targetVarDef),
  873    createTargetInstanceParam(_class, _forwMethod, _targetVarDef),
  874    set_parent(_origParams,_forwMethod),
  875    rec_set_encl_method(_origParams,_forwMethod),
  876
  877    delete(methodT(_method, _class, _origName, _origParams, _type, _exceptions, _body)),
  878
  879    add(methodT(_method, _class, _origName, _newParams, _type, _exceptions, _forwBody)),
  880    add(methodT(_forwMethod, _class, _forwName, [_thisVarDef | [_targetVarDef |_origParams]], _type, _exceptions, _body)),
  881
  882    cloneModifier(_method,_forwMethod),
  883    add_to_class(_class, _forwMethod),
  884
  885    % add forwarding call
  886    ((_forwStmts == []) -> (
  887        new_ids([_execReturn,_thisIdent,_targetIdent]),
  888
  889        reccreateVarDefIdents(_forwCall, _newParams,_forwArgs),
  890        rec_set_encl_method(_forwArgs,_method),
  891        add(applyT(_forwCall, _execReturn,_method, 'null', _forwName, [_thisIdent| [_targetIdent | _forwArgs]], _forwMethod)),
  892        create_this_or_null_if_static(_thisIdent,   _forwCall, _method,  _class),
  893        create_this_or_null_if_static(_targetIdent, _forwCall, _method,  _class),
  894        createReturnOrExec(_forwBody, _forwMethod, _type, _forwCall, _execReturn),
  895        _bodyStmts = [_execReturn]
  896    );
  897        _bodyStmts = _forwStmts
  898    ),
  899    add(blockT(_forwBody, _method,_method, _bodyStmts)),%neu
  900    updateForwardsFact(_method,execution,_method,_forwMethod).
  901
  902
  903
  904createAroundBody(_call, _forwMethod, _forwBody, _ForwName,_forwParams, _Type) :-
  905    applyT(_call,_parent,_enclMethod,_expr,_origName,_args, _method),
  906    !,
  907    getOrigArgs(_call,_args,_origArgs),
  908    new_ids([_forwCall, _forwMethIdent]),
  909%    applyT(_call, _parent, _enclMethod, _origReceiver, _),
  910    method(_method, DeclaringType, _origName, _, _Type, _exc, _),
  911    forwardingMethodName(_call, 'call$',_origName, _ForwName),
  912    enclClass(_enclMethod,_enclClass),
  913    createForwMethParams(_enclClass,_forwMethod,DeclaringType,_expr,_origArgs,_forwParams),
  914    replaceId(_parent, _call, _forwCall),
  915    createForwArgs(_call,_enclMethod,_enclClass,_forwCall,_origReceiver,_args,_forwArgs,DeclaringType),
  916    set_parent(_forwArgs,_forwCall),
  917    add(applyT(_forwCall, _parent,_enclMethod, 'null', _ForwName, _forwArgs, _forwMethod)),
  918%    retractall(applyT(_call, _,_,_,__,_)), %new: remove old forwarding Appl
  919    updateForwardsFact(_call,methodCall,_forwCall,_forwMethod).%new: update