note description: "[ A class visitor to create a proxy class. - Actual generic parameters and generic constraints are taken over unmodified from the original class. - Each proxy only has the processor setter as its creation routine, with one exception: Proxies for expanded original classes additionally list the default create routine, because this is an Eiffel requirement. - It adds for each creation routine a creation routine wrapper and an effective creation routine wrapper. The creation routine wrapper can be used by a client to issue a creation routine call on a separate processor. For this the creation routine wrapper creates an agent to the effective creation routine wrapper and adds it to the request queue of the proxy processor. These wrappers are always effective, because creation routines are always effective. - Aliased features are transformed to non-aliased features both in the inheritance clause and in the feature names. ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class SCOOP_SEPARATE_PROXY_PRINTER inherit SCOOP_CONTEXT_AST_PRINTER redefine process_class_as, process_feature_clause_as, process_feature_as, process_type_dec_as, process_class_list_as, process_create_as, process_keyword_as, process_invariant_as end SCOOP_CLASS_NAME export {NONE} all end INTERNAL_COMPILER_STRING_EXPORTER create make, make_with_default_context feature {NONE} -- Initialization make (a_ctxt: ROUNDTRIP_CONTEXT) -- Initialize, set `context' with `a_ctxt'. require a_ctxt_not_void: a_ctxt /= Void do context := a_ctxt end make_with_default_context -- Initialize, create context of type `ROUNDTRIP_STRING_LIST_CONTEXT'. do make (create {ROUNDTRIP_STRING_LIST_CONTEXT}.make) end feature -- Access add_proxy_class -- Add a client class for the original class indicated in the workbench. do -- initialize type visitors for visiting signatures and locals l_type_signature := scoop_visitor_factory.new_proxy_type_signature_printer (context) l_type_locals := scoop_visitor_factory.new_proxy_type_local_printer (context) -- start class processing process_class_as (class_as) end feature {NONE} -- Implementation process_class_as (l_as: CLASS_AS) -- Process `l_as', the AST class node. require else class_as_not_void: class_as /= Void class_c_not_void: class_c /= Void local s: STRING_AS l_parent_visitor: SCOOP_PROXY_PARENT_VISITOR l_generics_visitor: SCOOP_GENERICS_VISITOR do -- inicial comments to indicate the automated class generation context.add_string ("-- This class has been generated by SCOOP2SCOOPLI") context.add_string ("%N-- It implements separate proxies for objects based on class " + class_as.class_name.name + "%N%N") -- since we produce only override classes we skip the indexing part -- safe_process (l_as.internal_top_indexes) if l_as.internal_top_indexes /= Void then last_index := l_as.internal_top_indexes.last_token (match_list).index end safe_process (l_as.frozen_keyword (match_list)) safe_process (l_as.deferred_keyword (match_list)) safe_process (l_as.external_keyword (match_list)) safe_process (l_as.class_keyword (match_list)) process_leading_leaves (l_as.class_name.index) process_class_name (l_as.class_name, True, context, match_list) if l_as.class_name /= Void then last_index := l_as.class_name.last_token (match_list).index end -- process internal generics if l_as.internal_generics /= Void then process_leading_leaves (l_as.internal_generics.index) l_generics_visitor := scoop_visitor_factory.new_generics_visitor (context) l_generics_visitor.process_class_internal_generics (l_as.internal_generics, false, False) last_index := l_generics_visitor.get_last_index end safe_process (l_as.alias_keyword (match_list)) s ?= l_as.external_class_name safe_process (s) safe_process (l_as.obsolete_keyword (match_list)) safe_process (l_as.obsolete_message) -- process parents l_parent_visitor := scoop_visitor_factory.new_proxy_parent_visitor (context) l_parent_visitor.process_internal_conforming_parents (l_as.internal_conforming_parents) l_parent_visitor.process_internal_non_conforming_parents (l_as.internal_non_conforming_parents) if l_as.conforming_parents /= Void or l_as.non_conforming_parents /= Void then last_index := l_parent_visitor.get_last_index end -- process creation and conversion clause add_creation_code (l_as.creators) -- process features safe_process (l_as.features) -- add SCOOP feature clause with reference to client object. context.add_string ("%N%Nfeature -- Separateness") -- add attribute of actual object context.add_string ("%N%N%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_implementation_getter_name + ": " + l_as.class_name.name.as_upper) -- formal paramters if l_as.internal_generics /= Void then l_generics_visitor.process_class_internal_generics (class_as.internal_generics, True, True) end context.add_string ("%N%T%T-- reference to actual object") -- add SCOOP feature: wrappers for creation features. if not l_as.is_deferred or l_as.is_expanded then context.add_string ("%N%Nfeature -- Creation Wrappers%N") if l_as.creators /= Void then last_index := l_as.creators.index - 1 safe_process (l_as.creators) else add_default_create_wrappers end end -- Skip invariant. if l_as.internal_invariant /= Void then last_index := l_as.internal_invariant.last_token (match_list).index end -- Skip indexes. last_index := l_as.end_keyword.index - 1 -- process end keyword context.add_string ("%N%N") safe_process (l_as.end_keyword) end process_feature_clause_as (l_as: FEATURE_CLAUSE_AS) -- Process `l_as', the AST feature clause list. do -- remember the current feature clause set_current_feature_clause_as (l_as) -- process feature clause last_index := l_as.first_token (match_list).index context.add_string ("%N%N") safe_process (l_as.feature_keyword) -- Remove the clients. if l_as.clients /= void then last_index := l_as.clients.last_token (match_list).index end -- process feature clause comment if not l_as.features.is_empty then process_leading_leaves (l_as.features.first_token (match_list).index) else process_leading_leaves (l_as.last_token (match_list).index + 1) end -- set value for pretty printing set_is_first_feature (True) -- process features safe_process (l_as.features) -- reset the current feature clause set_current_feature_clause_as_void end process_feature_as (l_as: FEATURE_AS) -- Process `l_as', the AST feature node, invokes the `SCOOP_PROXY_FEATURE_VISITOR'. local l_feature_visitor: SCOOP_PROXY_FEATURE_VISITOR l_feature_object: SCOOP_CLIENT_FEATURE_OBJECT do create l_feature_object.make set_feature_object (l_feature_object) l_feature_visitor := scoop_visitor_factory.new_proxy_feature_visitor (context) l_feature_visitor.add_proxy_features(l_as) last_index := l_as.last_token (match_list).index end process_create_as (l_as: CREATE_AS) -- Process `l_as', the class creation feature list. -- Call `process_default_create_wrappers' when a `default_create' feature is listed. local i, nb: INTEGER l_is_creator_default_create: BOOLEAN l_feature_name_visitor: SCOOP_FEATURE_NAME_VISITOR l_feature_name: STRING do if l_as.feature_list /= Void then l_feature_name_visitor := scoop_visitor_factory.new_feature_name_visitor from i := 1 nb := l_as.feature_list.count until i > nb loop l_feature_name_visitor.process_feature_name (l_as.feature_list.i_th (i), False) l_feature_name := l_feature_name_visitor.feature_name if l_feature_name.is_equal (system.any_class.compiled_class.default_create_feature.feature_name) then l_is_creator_default_create := True else add_creation_procedure_wrappers (l_feature_name) end i := i + 1 end if l_is_creator_default_create then add_default_create_wrappers end end end process_type_dec_as (l_as: TYPE_DEC_AS) -- Process 'l_as', the internal argument list. do process_identifier_list (l_as.id_list) safe_process (l_as.colon_symbol (match_list)) -- process type l_type_signature.process_type (l_as.type) end process_class_list_as (l_as: CLASS_LIST_AS) -- Process `l_as', the class list node. -- If a class name (other than ANY or NONE) appears in the list, add its separate proxy as well. do safe_process (l_as.lcurly_symbol (match_list)) -- add class names with prefix if l_as /= Void then process_class_name_list_with_prefix (l_as, True, context, match_list) end last_index := l_as.rcurly_symbol_index - 1 safe_process (l_as.rcurly_symbol (match_list)) end process_keyword_as (l_as: KEYWORD_AS) -- Process `l_as', the AST keyword node. do if l_as.is_separate_keyword then -- skip last_index := l_as.index elseif l_as.is_frozen_keyword then Precursor (l_as) -- add a space context.add_string (" ") elseif l_as.is_prefix_keyword or l_as.is_infix_keyword then -- skip Precursor (l_as) context.add_string ("_") else Precursor (l_as) end end process_invariant_as (l_as: INVARIANT_AS) -- Process `l_as', the AST invariant node. do -- skip node if l_as.full_assertion_list /= Void then last_index := l_as.last_token (match_list).index end end add_creation_code (l_as: EIFFEL_LIST [CREATE_AS]) -- Process creators and convertors do -- creator & convertor if not class_as.is_deferred then -- creator -- context.add_string ("%N%Ncreate%N%Tmake_from_local, set_processor_") context.add_string ("%N%Ncreate%N%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_setter_name) if class_as.is_expanded then context.add_string (", ") context.add_string ({SCOOP_SYSTEM_CONSTANTS}.scoop_library_proxy_any_default_create_feature_name) end end -- skip original creators and convertors if class_as.creators /= Void or class_as.convertors /= Void then if class_as.features /= Void then last_index := class_as.features.index - 1 elseif class_as.internal_invariant /= Void then last_index := class_as.internal_invariant.first_token (match_list).index - 1 elseif class_as.internal_bottom_indexes /= Void then last_index := class_as.internal_bottom_indexes.index -1 else last_index := class_as.end_keyword.index - 1 end end end add_default_create_wrappers -- Generate two additional procedures: -- `default_create_scoop_separate_class_name' and `effective_default_create_scoop_separate_class_name' -- for wrapping creation instructions. do -- 'default_create_scoop_separate_class_name' context.add_string ("%N%Nfeature -- default creation instruction wrapper") context.add_string ("%N%N%Tdefault_create_scoop_separate_") context.add_string (class_as.class_name.name.as_lower) context.add_string (" (" + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + ": attached " + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_separate_client_class_name + ")") context.add_string ("%N%T%T%T") context.add_string ("-- Wrapper for creation procedure `default_create'.%N%T%T") context.add_string ("%N%T%Tdo") context.add_string ( "%N%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_asynchronous_execute_feature_name + " (" + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + ", " + "agent " + {SCOOP_SYSTEM_CONSTANTS}.effective_creation_routine_wrapper_name_additive + system.any_class.compiled_class.default_create_feature.feature_name + {SCOOP_SYSTEM_CONSTANTS}.general_wrapper_name_additive + class_as.class_name.name.as_lower + ")" ) context.add_string ("%N%T%Tend") -- 'effective_default_create_scoop_separate_class_name' context.add_string ("%N%N%T" + {SCOOP_SYSTEM_CONSTANTS}.effective_creation_routine_wrapper_name_additive + system.any_class.compiled_class.default_create_feature.feature_name + {SCOOP_SYSTEM_CONSTANTS}.general_wrapper_name_additive + class_as.class_name.name.as_lower + " is") context.add_string ("%N%T%T%T-- Wrapper for creation procedure `default_create'.") context.add_string ("%N%T%Tdo") context.add_string ("%N%T%Tend%N") end add_creation_procedure_wrappers (a_feature_name: STRING) -- Generate two additional procedures: -- `feature_name_scoop_separate_class_name' and `effective_feature_name_scoop_separate_class_name' -- for wrapping creation instructions. require a_feature_name_is_valid: class_c.feature_named (a_feature_name) /= Void local l_feature_i: FEATURE_I l_feature_as: FEATURE_AS do l_feature_i := class_c.feature_named (a_feature_name) match_list := match_list_server.item (l_feature_i.written_class.class_id) l_type_signature.set_match_list (match_list) context.add_string ("%N%Nfeature -- creation instruction wrapper") l_feature_as := l_feature_i.body if l_feature_as /= Void and l_feature_as.body /= Void then context.add_string ("%N%N%T" + a_feature_name + {SCOOP_SYSTEM_CONSTANTS}.general_wrapper_name_additive + class_as.class_name.name.as_lower + " ") if l_feature_as.body.internal_arguments /= Void then -- print type with prefix last_index := l_feature_as.body.internal_arguments.first_token (match_list).index - 1 add_formal_argument_list (l_feature_as.body.internal_arguments, true) last_index := l_feature_as.body.internal_arguments.last_token (match_list).index else context.add_string ("(" + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + ": attached " + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_separate_type_class_name + ") ") --CLIENT) ") end context.add_string ("%N%T%T%T") context.add_string ("-- Wrapper for creation procedure `" + a_feature_name + "'.%N%T%T") context.add_string ("%N%T%Tlocal") context.add_string ("%N%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.client_agent_local_name + ": " + system.procedure_class.name + "[" + system.any_class.name + ", " + system.tuple_class.name + "]") add_lock_passing_detection_code (l_feature_as) context.add_string ("%N%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.client_agent_local_name + " := agent ") -- + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_implementation_getter_name + ".") context.add_string ({SCOOP_SYSTEM_CONSTANTS}.effective_creation_routine_wrapper_name_additive + a_feature_name + {SCOOP_SYSTEM_CONSTANTS}.general_wrapper_name_additive + class_as.class_name.name.as_lower) if l_feature_as.body.internal_arguments /= Void then add_actual_argument_list (l_feature_as.body.internal_arguments, False, True, False) end context.add_string ("%N%T%T%T"+{SCOOP_SYSTEM_CONSTANTS}.async_call_name) context.add_string ("(" + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name) context.add_string ("," + {SCOOP_SYSTEM_CONSTANTS}.lock_passing_detector_local_name) context.add_string ("," + {SCOOP_SYSTEM_CONSTANTS}.client_agent_local_name) context.add_string (")") context.add_string ("%N%T%Tend") end -- 'effective_feature_name_scoop_separate_class_name' context.add_string ("%N%N%T" + {SCOOP_SYSTEM_CONSTANTS}.effective_creation_routine_wrapper_name_additive + a_feature_name + {SCOOP_SYSTEM_CONSTANTS}.general_wrapper_name_additive + class_as.class_name.name.as_lower + " ") if l_feature_as.body.internal_arguments /= Void then last_index := l_feature_as.body.internal_arguments.first_token (match_list).index - 1 add_formal_argument_list (l_feature_as.body.internal_arguments, false) last_index := l_feature_as.body.internal_arguments.last_token (match_list).index end context.add_string ("%N%T%T%T-- Wrapper for creation procedure `" + a_feature_name + "'.") context.add_string ("%N%T%Tdo") context.add_string ("%N%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_implementation_getter_name + "." + a_feature_name) if l_feature_as.body.internal_arguments /= Void then context.add_string (" ") add_actual_argument_list (l_feature_as.body.internal_arguments, false, true, true) end context.add_string ("%N%T%Tend") match_list := match_list_server.item (class_c.class_id) l_type_signature.set_match_list (match_list) end add_client_agent_local (a_feature: FEATURE_AS) -- Add a local for an agent to 'a_feature' of a client object. local l_feature_name,feature_name: FEATURE_NAME i: INTEGER l_assign_finder: SCOOP_PROXY_ASSIGN_FINDER l_generics_visitor: SCOOP_GENERICS_VISITOR generics_to_substitute: LINKED_LIST[TUPLE[INTEGER,INTEGER]] do -- Get Feature name object from i := 1 until i > a_feature.feature_names.count loop l_feature_name := a_feature.feature_names.i_th (i) if l_feature_name.internal_name.is_equal (a_feature.feature_name) then feature_name := l_feature_name end i := i + 1 end if a_feature.is_function or a_feature.is_attribute or a_feature.is_constant then context.add_string ("%N%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.client_agent_local_name + ": " + system.function_class.name + "[" + system.any_class.name + ", " + system.tuple_class.name + ", ") if a_feature.body.type /= void then -- Fix for redeclarations if feature is query type: -- If `l_as.type' is non separate but was separate in an ancestor version we need to make it separate -- Only a potential problem when return type is `non-separate' and a `CLASS_TYPE_AS' if attached {CLASS_TYPE_AS} a_feature.body.type as typ then create l_assign_finder if not typ.has_separate_mark then if l_assign_finder.have_to_replace_return_type(feature_name, class_c) then context.add_string ({SCOOP_SYSTEM_CONSTANTS}.proxy_class_prefix+typ.class_name.name) add_result_substitution := true -- Remember we added the substitution so we dont add `proxy_' later else -- No substitution needed, print normaly context.add_string (typ.class_name.name) end else -- Separate: No substitution needed, print normaly context.add_string ({SCOOP_SYSTEM_CONSTANTS}.proxy_class_prefix+typ.class_name.name) end else -- Nothing was done, no generics -> process normally l_type_locals.process_type (a_feature.body.type) end -- Print generics and check if they need a substitution if attached {GENERIC_CLASS_TYPE_AS} a_feature.body.type as gen_typ then create l_assign_finder l_generics_visitor := scoop_visitor_factory.new_generics_visitor (context) generics_to_substitute := l_assign_finder.generic_parameters_to_replace (feature_name, class_c, False, Void, True) if not generics_to_substitute.is_empty then l_generics_visitor.set_generics_to_substitute (generics_to_substitute) end l_generics_visitor.process_internal_generics (gen_typ.generics, false, True) end last_index := a_feature.body.type.last_token (match_list).index end context.add_string ("]") end end add_lock_passing_detection_code (a_feature: FEATURE_AS) -- Add lock passing detection code together with the do keyword. For each non-ignored, non-expanded, attached formal argument, add lock passing detection code that stores the result in the generated locals. Ignored classes do not have a processor. Objects of expanded type get passed as a copy. Detachable formal arguments do not get locked and hence do not contribute to lock passing. local l_formal_arguments: FORMAL_ARGU_DEC_LIST_AS l_formal_argument_group: TYPE_DEC_AS i, j: INTEGER l_type_expr_visitor: SCOOP_TYPE_EXPR_VISITOR do -- Add locals used for lock passing. context.add_string ("%N%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.lock_passing_detector_local_name + ": " + {SCOOP_SYSTEM_CONSTANTS}.lock_passing_detector_local_type) -- Add the do keyword. context.add_string ("%N%T%Tdo") -- For each non-ignored, non-expanded, attached formal argument, add lock passing detection code. if a_feature.body.internal_arguments /= void and then a_feature.body.internal_arguments.arguments /= void then from l_formal_arguments := a_feature.body.internal_arguments i := 1 l_type_expr_visitor := scoop_visitor_factory.new_type_expr_visitor until i > l_formal_arguments.arguments.count loop l_formal_argument_group := l_formal_arguments.arguments.i_th (i) l_type_expr_visitor.resolve_type_in_workbench (l_formal_argument_group.type) from j := 1 until j > l_formal_argument_group.id_list.count loop if not is_in_ignored_group (l_type_expr_visitor.resolved_type.associated_class) and not l_type_expr_visitor.resolved_type.is_expanded and attached {ATTACHABLE_TYPE_A} l_type_expr_visitor.resolved_type as attachable_resolved_type and then (attachable_resolved_type.has_attached_mark or not attachable_resolved_type.has_detachable_mark) then context.add_string ("%N%T%T%Tif attached {" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_separate_type_class_name + "} " + l_formal_argument_group.item_name (j) + " as " + {SCOOP_SYSTEM_CONSTANTS}.general_generated_entity_name + " then") context.add_string ( "%N%T%T%T%Tif " + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_locked_processors_has_query_name + " (" + {SCOOP_SYSTEM_CONSTANTS}.general_generated_entity_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + ") then" ) context.add_string ("%N%T%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.lock_passing_detector_local_name + " := true") context.add_string ("%N%T%T%T%Tend") context.add_string ("%N%T%T%Tend") end j := j + 1 end i := i + 1 end end end add_actual_argument_list (a_list: FORMAL_ARGU_DEC_LIST_AS; a_with_a_caller: BOOLEAN; a_with_brackets: BOOLEAN; a_is_for_client_call: BOOLEAN) -- Add an actual argument list that is based on 'a_list'. -- If 'a_is_for_client_call' is true then the actual argument list is generated for a call to a client object. Otherwise the generated actual argument list is generated for a call to a proxy object. The actual argument list for a client object takes care that the actual arguments get converted according to the signature of the client feature. -- If 'a_with_a_caller' is true then the actual argument list has the caller as the first actual argument. -- If 'a_with_brackets' is true then the actual argument list is enclosed with parentheses. local i: INTEGER j: INTEGER l_formal_argument_group: TYPE_DEC_AS l_type_expr_visitor: SCOOP_TYPE_EXPR_VISITOR do -- Add a opening paranthesis, if requested. if a_with_brackets then context.add_string ("(") end -- Add the caller as an actual argument, if requested. if a_with_a_caller then context.add_string ({SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + ", ") end -- Go through the list of formal arguments and add them to the generated actual argument list. if a_list.arguments /= Void then from i := 1 l_type_expr_visitor := scoop_visitor_factory.new_type_expr_visitor until i > a_list.arguments.count loop l_formal_argument_group := a_list.arguments.i_th (i) l_type_expr_visitor.resolve_type_in_workbench (l_formal_argument_group.type) from j := 1 until j > l_formal_argument_group.id_list.count loop -- Do we generated an actual argument list for a client object? if a_is_for_client_call then -- Yes, we do. -- Is the type of the current formal argument based on an ignored class? if is_in_ignored_group (l_type_expr_visitor.resolved_type.associated_class) then -- Yes, it is. -- Ignored classes do not get replaced with a client and a proxy class. We do not have to convert the formal argument. context.add_string (l_formal_argument_group.item_name (j)) else -- No, it is not. -- Is the type of the current formal argument expanded? if l_type_expr_visitor.resolved_type.is_expanded then -- Yes, it is. -- Expanded types are transformed to client types in both client and proxy classes. No conversion is necessary. context.add_string (l_formal_argument_group.item_name (j)) else -- Not, it isn't. -- Is the type of the current formal argument separate? if l_type_expr_visitor.resolved_type.is_separate then -- Yes, it is. -- Has the current formal argument in the original class been redeclared from non-separate to separate? if feature_object.is_internal_arguments_to_substitute_defined and then feature_object.internal_arguments_to_substitute.there_exists ( agent ( a_internal_arguments_to_substitute_name_identifier: INTEGER; a_formal_argument_name_identifier: INTEGER ): BOOLEAN do Result := a_internal_arguments_to_substitute_name_identifier.is_equal (a_formal_argument_name_identifier) end (?, l_formal_argument_group.id_list.i_th (j)) ) then -- Yes, it has. -- In the client class, the formal argument remains non-separate. In the proxy class the formal argument has a proxy type. We need to convert the current formal argument to a client object. context.add_string (l_formal_argument_group.item_name (j)) context.add_string (".") context.add_string ({SCOOP_SYSTEM_CONSTANTS}.scoop_library_implementation_getter_name) else -- No, it hasn't. -- Both the client class and the proxy class use a proxy type for the formal argument. No conversion is necessary. context.add_string (l_formal_argument_group.item_name (j)) end else -- No it isn't. -- Is the type of the current formal argument based on a formal generic parameter? if l_type_expr_visitor.is_resolved_type_based_on_formal_generic_parameter or (feature_as /= Void and then parent_argument_is_formal (feature_as.feature_name.name_id, i)) then -- Yes, it is. -- Formal generic parameters are always non-separate in proxy classes. No conversion is necessary. context.add_string (l_formal_argument_group.item_name (j)) else -- No, it isn't. -- In the client class, the formal argument is non-separate. In the proxy class the formal argument has a proxy type. We need to convert the current formal argument to a client object. context.add_string (l_formal_argument_group.item_name (j)) context.add_string (".") context.add_string ({SCOOP_SYSTEM_CONSTANTS}.scoop_library_implementation_getter_name) end end end end else -- No, we don't. -- Proxy features have compatible signatures. We do not have to convert. context.add_string (l_formal_argument_group.item_name (j)) end -- Print the comma separator between actual arguments. if j < l_formal_argument_group.id_list.count or (j = l_formal_argument_group.id_list.count and i < a_list.arguments.count) then context.add_string (", ") end j := j + 1 end i := i + 1 end end -- Add a closing paranthesis, if requested. if a_with_brackets then context.add_string (")") end end add_formal_argument_list (a_list: FORMAL_ARGU_DEC_LIST_AS; a_is_with_a_caller: BOOLEAN) -- Add an formal argument list that is based on 'a_list'. -- If 'a_with_a_caller' is true then the formal argument list has the caller as the first formal argument. local pos,i, j, nb, nbj: INTEGER l_argument: TYPE_DEC_AS l_assign_finder: SCOOP_PROXY_ASSIGN_FINDER generics_to_substitute: LINKED_LIST[TUPLE[INTEGER,INTEGER]] interal_argument_to_substitute: TUPLE[pos:INTEGER;type:TYPE_AS] feature_name: FEATURE_NAME do context.add_string ("(") if a_is_with_a_caller then context.add_string ({SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + ": attached " + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_separate_type_class_name + "; ") end if a_list.arguments /= Void then pos := 1 from i := 1 nb := a_list.arguments.count until i > nb loop l_argument := a_list.arguments.i_th (i) from j := 1 nbj := l_argument.id_list.count until j > nbj loop context.add_string (l_argument.item_name (j) + ": ") -- Added by trosim, 2010-05-26 if l_argument.type.has_attached_mark then context.add_string ("attached ") elseif l_argument.type.has_detachable_mark then context.add_string ("detachable ") end if attached {GENERIC_CLASS_TYPE_AS} l_argument.type as gen_typ then create l_assign_finder create interal_argument_to_substitute.default_create interal_argument_to_substitute.pos := pos interal_argument_to_substitute.type := gen_typ if feature_as /= void then from feature_as.feature_names.start until feature_as.feature_names.after loop if feature_as.feature_names.item.visual_name.is_equal (feature_as.feature_name.name) then feature_name := feature_as.feature_names.item end feature_as.feature_names.forth end generics_to_substitute := l_assign_finder.generic_parameters_to_replace (feature_name, class_c, False, interal_argument_to_substitute, False) if not generics_to_substitute.is_empty then l_type_signature.set_generics_to_substitute (generics_to_substitute) end end end if attached feature_as as feat then l_type_signature.set_from_formal (parent_argument_is_formal (feat.feature_name.name_id, i)) end l_type_signature.process_type (l_argument.type) if attached {CLASS_TYPE_AS} l_argument.type as typ then if typ.has_separate_mark then if feature_as /= void then if need_internal_argument_substitution(feature_as.feature_name, class_c, pos) then feature_object.internal_arguments_to_substitute.append (l_argument.id_list) end end end end pos := pos +1 if i < nb or (i = nb and j < l_argument.id_list.count) then context.add_string ("; ") end j := j + 1 end i := i + 1 end end context.add_string (")") end parent_result_is_formal (feature_id : INTEGER) : BOOLEAN local parents : LIST [CLASS_C] i : INTEGER do parents := class_c.parents_classes from i := 1 until i > parents.count or Result loop if attached parents [i].feature_table.item_id (feature_id) as feat then Result := attached {FORMAL_A} feat.type end i := i + 1 end end parent_argument_is_formal (feature_id : INTEGER; arg_num : INTEGER) : BOOLEAN local parents : LIST [CLASS_C] i : INTEGER do parents := class_c.parents_classes from i := 1 until i > parents.count or Result loop Result := is_inherited_generic (parents [i], feature_id, arg_num) i := i + 1 end end is_inherited_generic (a_class : CLASS_C; feature_id, arg_num : INTEGER ) : BOOLEAN do if attached a_class.feature_table.item_id (feature_id) as feat then Result := attached {FORMAL_A} feat.arguments [arg_num] end end add_lock_passing_code -- Add code for lock passing. do context.add_string ("%N%T%T%Tif " + {SCOOP_SYSTEM_CONSTANTS}.lock_passing_detector_local_name + " then") context.add_string ("%N%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.locked_processors_stack_size_local_name + " := " + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_locked_processors_count_query_name) context.add_string ("%N%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.synchronous_processors_stack_size_local_name + " := " + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_synchronous_processors_count_query_name) context.add_string ("%N%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_locked_processors_push_whole_stack_command_name + "(" + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_locked_processors_query_name + ")") context.add_string ("%N%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_synchronous_processors_push_whole_stack_command_name + "(" + {SCOOP_SYSTEM_CONSTANTS}.caller_formal_argument_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_synchronous_processors_query_name + ")") end add_lock_revocation_code -- Add code for lock revokation. do context.add_string ("%N%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_synchronous_processors_trim_command_name + " (" + {SCOOP_SYSTEM_CONSTANTS}.synchronous_processors_stack_size_local_name + ")") context.add_string ("%N%T%T%T%T" + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_processor_getter_name + "." + {SCOOP_SYSTEM_CONSTANTS}.scoop_library_locked_processors_trim_command_name + " (" + {SCOOP_SYSTEM_CONSTANTS}.locked_processors_stack_size_local_name + ")") context.add_string ("%N%T%T%Telse") end need_internal_argument_substitution(a_feature_name: ID_AS; a_class_c: CLASS_C; arg_pos: INTEGER): BOOLEAN -- Do we need a redeclaration substitution for internal arguments? -- Needed when current argument is separate and parent version was non separate local l_assign_finder: SCOOP_PROXY_ASSIGN_FINDER feature_i: FEATURE_I l_feature_name: FEATURE_NAME has_context: BOOLEAN do create l_assign_finder feature_i := a_class_c.feature_named (a_feature_name.name) if feature_i /= Void then from feature_i.body.feature_names.start until feature_i.body.feature_names.after loop if feature_i.body.feature_names.item.visual_name.is_equal (a_feature_name.name) then l_feature_name := feature_i.body.feature_names.item end feature_i.body.feature_names.forth end if a_class_c = class_c then has_context := true end if a_feature_name /= void and a_class_c.feature_table.item (l_feature_name.internal_name.name).arguments /= Void and then l_assign_finder.have_to_replace_internal_arguments (l_feature_name, a_class_c, arg_pos) then Result := True end end end add_result_substitution: BOOLEAN -- Is the result type of the feature beeing changed from non separate to separate? -- Is the case when a feature with non separate return type has a parent feature redeclaration with separate return type. l_type_signature: SCOOP_PROXY_TYPE_SIGNATURE_PRINTER -- prints 'TYPE_AS' to the context l_type_locals: SCOOP_PROXY_TYPE_LOCALS_PRINTER -- prints 'TYPE_AS' to the context ;note copyright: "Copyright (c) 1984-2010, Chair of Software Engineering" license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" licensing_options: "http://www.eiffel.com/licensing" copying: "[ This file is part of Eiffel Software's Eiffel Development Environment. Eiffel Software's Eiffel Development Environment is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License (available at the URL listed under "license" above). Eiffel Software's Eiffel Development Environment is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eiffel Software's Eiffel Development Environment; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ]" source: "[ ETH Zurich Chair of Software Engineering Website http://se.inf.ethz.ch/ ]" end -- class SCOOP_SEPARATE_PROXY_PRINTER