-- This file is part of SmartEiffel The GNU Eiffel Compiler. -- Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE -- Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr -- http://SmartEiffel.loria.fr -- SmartEiffel 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; either version 2, or (at your option) any later -- version. SmartEiffel 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 SmartEiffel; see the file COPYING. If not, -- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- Boston, MA 02111-1307, USA. -- class E_INSPECT -- -- The Eiffel inspect instruction. -- inherit INSTRUCTION creation make feature start_position: POSITION -- Of keyword `inspect'. expression: EXPRESSION -- Heading expression after keyword `inspect'. when_list: WHEN_LIST -- List of when clauses. else_position: POSITION -- Of the keyword `else' if any. else_compound: COMPOUND -- Else compound if any. is_pre_computable: BOOLEAN is false end_mark_comment: BOOLEAN is true afd_check is do expression.afd_check if when_list /= Void then when_list.afd_check end if else_compound /= Void then else_compound.afd_check end end safety_check is do expression.safety_check if when_list /= Void then when_list.safety_check end if else_compound /= Void then else_compound.safety_check end end includes(v: INTEGER): BOOLEAN is -- True if a when clause includes `v'. do Result := when_list.includes_integer(v) end includes_between(low, up: INTEGER): BOOLEAN is -- True if a when clause includes an integer between `low' and -- `up' (inclusive). do Result := when_list.includes_integer_between(low,up) end collect_c_tmp is do expression.collect_c_tmp end compile_to_c is local no_check, all_check: BOOLEAN do no_check := ace.no_check all_check := ace.all_check cpp.inspect_incr cpp.put_string(once "/*[INSPECT*/%N{int ") cpp.put_inspect cpp.put_character('=') if all_check then cpp.put_character('(') cpp.put_trace_or_sedb_expression(expression.start_position) cpp.put_character(',') end expression.compile_to_c if all_check then cpp.put_character(')') end cpp.put_string(fz_00) if when_list = Void then if else_position.is_unknown then if no_check then exceptions_handler.bad_inspect_value(start_position) end elseif else_compound /= Void then else_compound.compile_to_c end elseif use_c_switch_statement then cpp.put_string(once "switch(") cpp.put_inspect cpp.put_string(once "){%N") when_list.compile_to_c_switch(else_position) if else_position.is_unknown then if no_check then cpp.put_string(once "default:;%N") exceptions_handler.bad_inspect_value(start_position) end elseif else_compound /= Void then cpp.put_string(once "default:;%N") else_compound.compile_to_c end cpp.put_string(once "}%N") else when_list.compile_to_c(else_position) if else_position.is_unknown then if no_check then cpp.put_character(' ') cpp.put_string(fz_else) cpp.put_character('{') exceptions_handler.bad_inspect_value(start_position) cpp.put_character('}') end elseif else_compound /= Void then cpp.put_character(' ') cpp.put_string(fz_else) cpp.put_character('{') else_compound.compile_to_c cpp.put_character('}') end end cpp.put_string(once "}/*INSPECT]*/%N") cpp.inspect_decr end compile_to_jvm is do expression.compile_to_jvm if when_list /= Void then when_list.compile_to_jvm(else_position) end if else_compound /= Void then else_compound.compile_to_jvm elseif else_position.is_unknown then if ace.no_check then code_attribute.runtime_error_inspect(expression) end end if when_list /= Void then when_list.compile_to_jvm_resolve_branch end code_attribute.opcode_pop end use_current: BOOLEAN is do Result := Result or else expression.use_current if when_list /= Void then Result := Result or else when_list.use_current end if else_compound /= Void then Result := Result or else else_compound.use_current end end stupid_switch(run_time_set: RUN_TIME_SET): BOOLEAN is do if expression.stupid_switch(run_time_set) then if (when_list = Void or else when_list.stupid_switch(run_time_set)) then if (else_compound = Void or else else_compound.stupid_switch(run_time_set)) then Result := true end end end end to_runnable(ct: E_TYPE): like Current is local e: like expression te: E_TYPE wl: WHEN_LIST do if current_type = Void then current_type := ct e := expression.to_runnable(ct) if nb_errors = 0 then expression := e te := e.result_type end if nb_errors = 0 then if te.is_character then if when_list /= Void then when_list := when_list.to_runnable_character(Current) if when_list = Void then error(start_position,em1) end end elseif te.is_integer then if when_list /= Void then when_list := when_list.to_runnable_integer(Current) if when_list = Void then error(start_position,em1) end end else error_handler.append("Expression must be INTEGER or CHARACTER.") error_handler.add_type(te," is not allowed.") error_handler.add_position(start_position) error_handler.print_as_error end end if else_compound /= Void then else_compound := else_compound.to_runnable(ct) end Result := Current else Result := twin if when_list /= Void then !!wl.from_when_list(when_list) Result.set_when_list(wl) end Result.clear_current_type Result := Result.to_runnable(ct) end end pretty_print is do pretty_printer.keyword(fz_inspect) pretty_printer.level_incr if not pretty_printer.zen_mode then pretty_printer.indent end pretty_printer.set_semi_colon_flag(false) expression.pretty_print pretty_printer.level_decr pretty_printer.indent if when_list /= Void then when_list.pretty_print end if else_compound = Void then if not else_position.is_unknown then pretty_printer.indent pretty_printer.keyword(fz_else) pretty_printer.put_character('%N') end else pretty_printer.indent pretty_printer.keyword(fz_else) pretty_printer.put_character('%N') else_compound.pretty_print end pretty_printer.indent pretty_printer.keyword(once "end;") if pretty_printer.print_end_inspect then pretty_printer.put_end(fz_inspect) end end feature {COMPOUND,INSTRUCTION_WITH_COMMENT} verify_scoop(allowed: FORMAL_ARG_LIST) is local dummy: BOOLEAN do dummy := expression.verify_scoop(allowed) if when_list /= Void then when_list.verify_scoop(allowed) end end feature {EIFFEL_PARSER} add_when(e_when: E_WHEN) is require e_when /= Void do if when_list = Void then !!when_list.make(e_when) else when_list.add_last(e_when) end end set_else_compound(sp: like else_position; ec: like else_compound) is do else_position := sp else_compound := ec end feature {E_INSPECT} set_when_list(wl: like when_list) is do when_list := wl ensure when_list = wl end clear_current_type is do current_type := Void ensure current_type = Void end feature {NONE} current_type: E_TYPE -- The one when runnable. make(sp: like start_position; exp: like expression) is require not sp.is_unknown exp /= Void do start_position := sp expression := exp ensure start_position = sp expression = exp end use_c_switch_statement: BOOLEAN is -- To decide if the generated C code is a true C "switch" or -- a sequence of "if... else if ... else ..."). do -- For the time being, this a naive implementation, because -- we may also consider wich C compiler is used (see in -- `system_tools'). If someone want to do this, I think we should add a -- new function named `use_c_switch_statement' in system_tools. -- Just post the fix in the mailing list. if when_list.largest_range_of_values <= 32 then Result := true end end em1: STRING is "Bad inspect." invariant expression /= Void end -- E_INSPECT