note description: "Abstract description of the body of an Eiffel feature." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class BODY_AS inherit AST_EIFFEL create initialize feature {NONE} -- Initialization initialize (a: like internal_arguments; t: like type; r: like assigner c: like content; c_as: detachable SYMBOL_AS; k_as: detachable LEAF_AS; a_as: detachable KEYWORD_AS; i_as: like indexing_clause) -- Create a new BODY AST node. do set_arguments (a) type := t assigner := r content := c if c_as /= Void then colon_symbol_index := c_as.index end if k_as /= Void then is_keyword_index := k_as.index end if a_as /= Void then assign_keyword_index := a_as.index end indexing_clause := i_as ensure internal_arguments_set: internal_arguments = a type_set: type = t assigner_set: assigner = r content_set: content = c colon_symbol_set: c_as /= Void implies colon_symbol_index = c_as.index is_keyword_set: k_as /= Void implies is_keyword_index = k_as.index assign_keyword_set: a_as /= Void implies assign_keyword_index = a_as.index indexing_clause_set: indexing_clause = i_as end feature -- Visitor process (v: AST_VISITOR) -- Process current element. do v.process_body_as (Current) end feature -- Roundtrip colon_symbol_index: INTEGER -- Index of symbol colon associated with this structure. is_keyword_index: INTEGER -- Index of keyword "is" or equal sign associated with this structure. assign_keyword_index: INTEGER -- Index of keyword "assign" associated with this structure. colon_symbol (a_list: LEAF_AS_LIST): detachable SYMBOL_AS -- Symbol colon associated with this structure. require a_list_not_void: a_list /= Void do Result := symbol_from_index (a_list, colon_symbol_index) end is_keyword (a_list: LEAF_AS_LIST): detachable LEAF_AS -- Keyword "is" or equal sign associated with this structure. require a_list_not_void: a_list /= Void local i: INTEGER do i := is_keyword_index if a_list.valid_index (i) then Result := a_list.i_th (i) end end assign_keyword (a_list: LEAF_AS_LIST): detachable KEYWORD_AS -- Keyword "assign" associated with this structure. require a_list_not_void: a_list /= Void do Result := keyword_from_index (a_list, assign_keyword_index) end internal_arguments: detachable FORMAL_ARGU_DEC_LIST_AS -- Internal list (of list) of arguments, in which "(" and ")" are stored. indexing_clause: detachable INDEXING_CLAUSE_AS -- Indexing clause in this structure. index: INTEGER -- <Precursor> do if attached content as l_content then Result := l_content.index end end feature -- Attributes arguments: detachable EIFFEL_LIST [TYPE_DEC_AS] -- List (of list) of arguments. do if attached internal_arguments as l_internal_arguments then Result := l_internal_arguments.arguments end ensure good_result: (internal_arguments = Void implies Result = Void) and (attached internal_arguments as l_args implies Result = l_args.arguments) end type: detachable TYPE_AS -- Type if any. assigner: detachable ID_AS -- Assigner mark if any. content: detachable CONTENT_AS -- Content of the body: constant or regular body. as_routine: detachable ROUTINE_AS -- See `content' as an instance of ROUTINE_AS. do if attached {ROUTINE_AS} content as l_routine then Result := l_routine end end as_constant: detachable CONSTANT_AS -- See `content' as an instance of CONSTANT_AS. do if attached {CONSTANT_AS} content as l_constant then Result := l_constant end end feature -- Roundtrip/Token first_token (a_list: detachable LEAF_AS_LIST): detachable LEAF_AS do if attached internal_arguments as l_args then Result := l_args.first_token (a_list) elseif colon_symbol_index /= 0 and a_list /= Void then Result := colon_symbol (a_list) elseif attached type as l_type then Result := l_type.first_token (a_list) elseif assign_keyword_index /= 0 and a_list /= Void then Result := assign_keyword (a_list) elseif attached assigner as l_assigner then Result := l_assigner.first_token (a_list) elseif is_keyword_index /= 0 and a_list /= Void then Result := is_keyword (a_list) elseif attached indexing_clause as l_indexing_clause then Result := l_indexing_clause.first_token (a_list) elseif attached content as l_content then Result := l_content.first_token (a_list) end end last_token (a_list: detachable LEAF_AS_LIST): detachable LEAF_AS do if a_list = Void then if attached content as l_content then Result := l_content.last_token (a_list) elseif attached type as l_type then Result := l_type.last_token (a_list) elseif attached arguments as l_args then Result := l_args.last_token (a_list) else Result := Void end else if attached content as l_content then if l_content.is_constant then if attached indexing_clause as l_indexing_clause then Result := l_indexing_clause.last_token (a_list) else Result := l_content.last_token (a_list) end else Result := l_content.last_token (a_list) end else -- Attribute case if attached indexing_clause as l_indexing_clause then Result := l_indexing_clause.last_token (a_list) elseif attached assigner as l_assigner then Result := l_assigner.last_token (a_list) elseif attached type as l_type then Result := l_type.last_token (a_list) end end end end feature -- Comparison is_equivalent (other: like Current): BOOLEAN -- Is `other' equivalent to the current object? do Result := equivalent (arguments, other.arguments) and equivalent (content, other.content) and equivalent (type, other.type) end feature -- Access has_instruction (i: INSTRUCTION_AS): BOOLEAN -- Does this body has instruction `i'? do if attached content as l_content then Result := l_content.has_instruction (i) else Result := False end end index_of_instruction (i: INSTRUCTION_AS): INTEGER -- Index of `i' in this body. -- Result is `0' not found. do if attached content as l_content then Result := l_content.index_of_instruction (i) else Result := 0 end end argument_index (n: INTEGER): INTEGER -- AST index of an argument number `n`if found, `0` otherwise. require valid_argument_number: n > 0 local id_list: IDENTIFIER_LIST distance: INTEGER do if attached arguments as a then distance := n across a as type_declaration until distance <= 0 loop id_list := type_declaration.id_list if distance > id_list.count then -- There are more declaration lists to go, skip this one. distance := distance - id_list.count else -- The argument should be in this declaration list. if attached id_list.id_list as argument_indexes then Result := argument_indexes [distance] end -- Exit the loop. distance := 0 end end end end feature -- Status report is_empty : BOOLEAN -- Is body empty? do Result := (not attached content as l_content) or else l_content.is_empty end feature -- default rescue create_default_rescue (def_resc_name_id: INTEGER) -- Create default rescue if necessary. require valid_feature_name_id: def_resc_name_id > 0 do if attached content as l_content then l_content.create_default_rescue (def_resc_name_id) end end feature -- Type check, byte code and dead code removal is_unique: BOOLEAN do Result := attached content as l_content and then l_content.is_unique end is_built_in: BOOLEAN -- Is current body a built in? do Result := attached content as l_content and then l_content.is_built_in end is_routine: BOOLEAN -- Is current body a routine? do -- If not a constant then current body is a routine. Result := attached content as l_content and then not l_content.is_constant end is_constant: BOOLEAN -- Is current body a constant? do Result := attached content as l_content and then l_content.is_constant end feature -- New feature description is_body_equiv (other: like Current): BOOLEAN -- Is the body of current feature equivalent to -- body of `other' ? do Result := equivalent (type, other.type) and then equivalent (arguments, other.arguments) if Result then if attached content as l_content and attached other.content as l_other_content then if l_content.is_constant = l_other_content.is_constant then -- The two objects are of the same type. -- There is no global typing problem. Result := l_content.is_body_equiv (l_other_content) else Result := False end else Result := content = other.content end end end is_assertion_equiv (other: like Current): BOOLEAN -- Is the assertion of Current feature equivalent to -- assertion of `other' ? --|Note: This test is valid since assertions are generated --|along with the body code. The assertions will be re-generated --|whenever the body has changed. Therefore it is not necessary to --|consider the cases in which one of the contents is a ROUTINE_AS --|and the other a CONSTANT_AS (The True value is actually returned --|but we don't care. --|Non-constant attributes have a Void content. In any case --|involving at least on attribute, the True value is retuned: --| . If they are both attributes, the assertions are equivalent --| . If only on is an attribute, we don't care since the bodies will --| not be equivalent anyway. --|The best way to understand all this, is to draw a two-dimensional --|table, for all possible combinations of the values (CONSTANT_AS, --|ROUTINE_AS, Void) of content and other.content) do if attached {ROUTINE_AS} content as r1 and attached {ROUTINE_AS} other.content as r2 then Result := r1.is_assertion_equiv (r2) else Result := True end end feature {BODY_AS, FEATURE_AS} -- Replication set_arguments (a: like internal_arguments) -- Set `internal_arguments' with `a'. do internal_arguments := a ensure internal_arguments_set: internal_arguments = a end set_type (t: like type) do type := t end set_content (c: like content) do content := c end note copyright: "Copyright (c) 1984-2023, Eiffel Software" 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: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end