-- 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_AGENT -- -- An agent definition as for example: agent foo("bar",?) -- inherit EXPRESSION creation make feature start_position: POSITION -- Of the "agent" keyword. is_current: BOOLEAN is false isa_dca_inline_argument: INTEGER is 0 dca_inline_argument(formal_arg_type: E_TYPE) is do end start_lookup_class: BASE_CLASS is do end is_pre_computable: BOOLEAN is false se_agent_id: INTEGER to_integer_or_error: INTEGER is do to_integer_error end to_runnable(ct: E_TYPE): like Current is local rc: RUN_CLASS; rt, rfrt: E_TYPE; bc: BASE_CLASS types: ARRAY[E_TYPE]; i: INTEGER; fal: FORMAL_ARG_LIST do if current_type = Void then current_type := ct feature_name := call.feature_name if base /= Void then rt := base.to_runnable(ct) if rt = Void then error_handler.add_position(base.start_position) error_handler.append("Bad BASE type for agent.") error_handler.print_as_fatal_error end create {FACE_TARGET} target.make(rt) else check target = Void end target := call.target.to_runnable(ct) if target = Void then error_handler.add_position(call.target.start_position) error_handler.append("Bad target for agent definition.") error_handler.print_as_fatal_error end end check target /= Void end rt := target.result_type rc := rt.run_class if rc /= Void then rt := rc.current_type bc := rc.base_class run_feature := bc.run_feature_for(rc,target, call.feature_name,ct) end arguments := call.arguments fal := run_feature.arguments if fal /= Void then if arguments = Void then -- Creating the ommited open argument list: arguments := fal.open_args(feature_name.start_position) end end if arguments /= Void then arguments := arguments.open_operands_notify(Current, run_feature) arguments := arguments.to_runnable(ct) if arguments = Void then error_handler.add_position(call.arguments.start_position) error_handler.append("Bad arguments for agent definition.") error_handler.print_as_fatal_error end end -- smart_eiffel.argument_passing_check(call.start_position, arguments,run_feature) -- Computing `result_type': if base /= Void then create types.with_capacity(4,1) types.add_last(base.run_type) end if open_args /= Void then if types = Void then create types.with_capacity(4,1) end from i := open_args.lower until i > open_args.upper loop types.add_last(open_args.item(i).result_type.run_type) i := i + 1 end end create open_tuple.make(start_position,types) rfrt := run_feature.result_type if rfrt = Void then create {TYPE_PROCEDURE} result_type.make(start_position,rt,open_tuple) else create {TYPE_FUNCTION} result_type.make(start_position,rt,open_tuple,rfrt) end check result_type = result_type.run_type end result_type.load_builtin_features se_agent_id := agent_pool.register(Current) -- Computing `definition_function_name': create definition_function_name.make(16) definition_function_name.append(as_agent) se_agent_id.append_in(definition_function_name) -- Computing `execution_function_name': create execution_function_name.make(16) execution_function_name.extend('_') execution_function_name.append(definition_function_name) -- Finally: result_type.run_class.set_at_run_time Result := Current else create Result.make(start_position,base,call) Result := Result.to_runnable(ct) end end result_type: TYPE_OF_AGENT is_void: BOOLEAN is false is_writable: BOOLEAN is false c_simple: BOOLEAN is false can_be_dropped: BOOLEAN is false is_manifest_string: BOOLEAN is false is_static: BOOLEAN is false is_result: BOOLEAN is false stupid_switch(run_time_set: RUN_TIME_SET): BOOLEAN is do end afd_check is local rc: RUN_CLASS; run_time_set: RUN_TIME_SET do rc := target.result_type.run_class run_time_set := rc.run_time_set if run_time_set.count = 0 then elseif run_time_set.count > 1 then switch_collection.update(target,run_feature) end target.afd_check if arguments /= Void then arguments.afd_check end end safety_check is do target.safety_check if arguments /= Void then arguments.safety_check end end collect_c_tmp is do run_feature.collect_c_tmp target.collect_c_tmp if arguments /= Void then arguments.collect_c_tmp end end compile_to_c is local i: INTEGER; boost, need_comma: BOOLEAN; e: EXPRESSION do cpp.put_string(definition_function_name) cpp.put_character('(') boost := ace.boost if not boost then cpp.put_string(once "&ds") need_comma := true end if base = Void then if need_comma then cpp.put_character(',') end target.mapping_c_arg(target.result_type) need_comma := true end if arguments /= Void then from i := 1 until i > arguments.count loop if is_closed_argument(i) then if need_comma then cpp.put_character(',') end e := arguments.expression(i) e.mapping_c_arg(e.result_type) need_comma := true end i := i + 1 end end cpp.put_character(')') end mapping_c_target(formal_type: E_TYPE) is do compile_to_c end mapping_c_arg(formal_arg_type: E_TYPE) is do compile_to_c end use_current: BOOLEAN is do if arguments /= Void then Result := arguments.use_current end if not Result then Result := target.use_current end end c_frame_descriptor(format, locals: STRING) is do check false end end assertion_check(tag: CHARACTER) is do not_yet_implemented end static_value: INTEGER is do check false end end bracketed_pretty_print, pretty_print is do pretty_printer.keyword(once "agent") if base /= void then pretty_printer.put_character('{') base.pretty_print pretty_printer.put_character('}') pretty_printer.put_character('.') end call.pretty_print end print_as_target is do pretty_printer.put_character('(') pretty_print pretty_printer.put_character(')') pretty_printer.put_character('.') end short, short_target is do not_yet_implemented end precedence: INTEGER is do Result := atomic_precedence end jvm_assign_creation, jvm_assign is do check false end end compile_to_jvm_into(dest: E_TYPE): INTEGER is do Result := 1 compile_to_jvm end compile_target_to_jvm, compile_to_jvm is local is_switched: BOOLEAN do if base = void then if target.result_type.run_class.run_time_set.count > 1 then is_switched := True end elseif base.run_class.run_time_set.count > 1 then is_switched := True end if not is_switched then compile_to_jvm_no_switch else compile_to_jvm_switch end end compile_to_jvm_no_switch is local idx: INTEGER space: INTEGER fcn: STRING i_argument: INTEGER i_open_argument: INTEGER open_argument_count: INTEGER switch: SWITCH arguments_count: INTEGER sfn: FEATURE_NAME rfc: RUN_FEATURE rfi: RUN_FEATURE sp: POSITION do create fcn.make(64) if arguments /= void then arguments_count := arguments.count else arguments_count := 0 end sp.set_in(result_type.run_class.base_class) create sfn.simple_feature_name(as_call,sp) rfc := result_type.run_class.at(sfn) create sfn.simple_feature_name(as_item,sp) rfi := result_type.run_class.at(sfn) if rfc /= void or rfi /= void then -- new agent object (FUNCTION, PROCEDURE, or PREDICATE) result_type.run_class.jvm_basic_new -- store target into agent object code_attribute.opcode_dup target.compile_to_jvm fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_target,fz_21) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1); -- store target -- arguments code_attribute.opcode_dup code_attribute.opcode_push_integer(arguments_count) idx := constant_pool.idx_class2(fz_21) code_attribute.opcode_anewarray(idx) idx := constant_pool.idx_fieldref3(fcn,as_arguments,fz_c2) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1) fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_arguments,fz_c2) code_attribute.opcode_dup space := result_type.jvm_stack_space code_attribute.opcode_getfield(idx,space+1); -- get arguments from i_argument := 1 until i_argument > arguments_count loop if is_closed_argument(i_argument) then code_attribute.opcode_dup code_attribute.opcode_push_integer(i_argument - 1) if arguments.expression(i_argument).result_type.is_basic_eiffel_expanded then push_jvm_expanded_argument_to_object_wrapper(arguments.expression(i_argument),run_feature.arguments.type(i_argument)) else space := arguments.expression(i_argument).standard_compile_to_jvm_into(run_feature.arguments.type(i_argument)) end code_attribute.opcode_aastore else open_argument_count := open_argument_count + 1 end i_argument := i_argument + 1 end code_attribute.opcode_pop -- method code_attribute.opcode_dup create fcn.make(64) if base = void then target.compile_to_jvm -- target object fcn.clear fcn.append(target.result_type.run_class.fully_qualified_name) idx := constant_pool.idx_methodref3(fcn,fz_c3,fz_c4); -- getClass code_attribute.opcode_invokevirtual(idx,-1) else fcn.clear fcn.append(base.run_class.fully_qualified_name) fcn.replace_all('/','.') idx := constant_pool.idx_string2(fcn) code_attribute.opcode_ldc(idx) idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_d1,fz_d2); -- forName code_attribute.opcode_invokestatic(idx,-1) end idx := constant_pool.idx_string(run_feature.name.to_string) -- the method name code_attribute.opcode_ldc(idx) code_attribute.opcode_push_integer(arguments_count) idx := constant_pool.idx_class2(fz_java_lang_class); -- array of java/lang/Class code_attribute.opcode_anewarray(idx) create fcn.make(64) from i_argument := 1 until i_argument > arguments_count loop code_attribute.opcode_dup code_attribute.opcode_push_integer(i_argument - 1) if arguments.expression(i_argument).result_type.is_basic_eiffel_expanded then push_jvm_expanded_argument_object_wrapper_type(run_feature.arguments.type(i_argument)) else fcn.clear fcn.append(ace.executable_name) fcn.extend('.') fcn.append(fz_jvm_root) idx := constant_pool.idx_string2(fcn) code_attribute.opcode_ldc(idx) idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_d1,fz_d2); -- forName code_attribute.opcode_invokestatic(idx,-1) end code_attribute.opcode_aastore i_argument := i_argument + 1 end idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_c6,fz_c7); -- getMethod code_attribute.opcode_invokevirtual(idx,-1) fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_method,fz_21) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1) -- get open_argument_count if base /= void then open_argument_count := open_argument_count + 1 end -- open_arguments code_attribute.opcode_dup code_attribute.opcode_push_integer(open_argument_count) idx := constant_pool.idx_class2(fz_21) code_attribute.opcode_anewarray(idx) idx := constant_pool.idx_fieldref3(fcn,as_open_arguments,fz_c2) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1) -- open_argument_indices code_attribute.opcode_dup code_attribute.opcode_push_integer(open_argument_count) code_attribute.opcode_newarray(10) -- array of int fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_open_argument_indices,fz_d3) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1); -- store open_argument_indices -- open_argument_indices contents code_attribute.opcode_dup fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_open_argument_indices,fz_d3) space := result_type.jvm_stack_space code_attribute.opcode_getfield(idx,space + 1); -- get open_argument_indices i_open_argument := 0 if base /= void then code_attribute.opcode_dup code_attribute.opcode_push_integer(i_open_argument) code_attribute.opcode_push_integer(-1) code_attribute.opcode_iastore i_open_argument := 1 end from i_argument := 1 until i_argument > arguments_count loop if not is_closed_argument(i_argument) then code_attribute.opcode_dup code_attribute.opcode_push_integer(i_open_argument) code_attribute.opcode_push_integer(i_argument - 1) code_attribute.opcode_iastore i_open_argument := i_open_argument + 1 end i_argument := i_argument + 1 end code_attribute.opcode_pop else code_attribute.opcode_aconst_null end end compile_to_jvm_switch is local idx: INTEGER space: INTEGER fcn: STRING i_argument: INTEGER i_open_argument: INTEGER open_argument_count: INTEGER switch: SWITCH arguments_count: INTEGER sfn: FEATURE_NAME rfc: RUN_FEATURE rfi: RUN_FEATURE sp: POSITION do create fcn.make(64) if arguments /= void then arguments_count := arguments.count else arguments_count := 0 end sp.set_in(result_type.run_class.base_class) create sfn.simple_feature_name(as_call,sp) rfc := result_type.run_class.at(sfn) create sfn.simple_feature_name(as_item,sp) rfi := result_type.run_class.at(sfn) if rfc /= void or rfi /= void then -- new agent object (FUNCTION, PROCEDURE, or PREDICATE) result_type.run_class.jvm_basic_new -- store target into agent object code_attribute.opcode_dup target.compile_to_jvm fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_target,fz_21) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1); -- store target -- arguments code_attribute.opcode_dup code_attribute.opcode_push_integer(arguments_count + 1) idx := constant_pool.idx_class2(fz_21) code_attribute.opcode_anewarray(idx) idx := constant_pool.idx_fieldref3(fcn,as_arguments,fz_c2) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1) fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_arguments,fz_c2) code_attribute.opcode_dup space := result_type.jvm_stack_space code_attribute.opcode_getfield(idx,space+1); -- get arguments if base = void then code_attribute.opcode_dup code_attribute.opcode_push_integer(0) target.compile_to_jvm -- target object is argument 0 for switch call code_attribute.opcode_aastore end from i_argument := 1 until i_argument > arguments_count loop if is_closed_argument(i_argument) then code_attribute.opcode_dup code_attribute.opcode_push_integer(i_argument) if arguments.expression(i_argument).result_type.is_basic_eiffel_expanded then push_jvm_expanded_argument_to_object_wrapper(arguments.expression(i_argument),run_feature.arguments.type(i_argument)) else space := arguments.expression(i_argument).standard_compile_to_jvm_into(run_feature.arguments.type(i_argument)) end code_attribute.opcode_aastore else open_argument_count := open_argument_count + 1 end i_argument := i_argument + 1 end code_attribute.opcode_pop -- method code_attribute.opcode_dup create fcn.make(64) fcn.clear fcn.append(ace.executable_name) fcn.extend('.') fcn.append(fz_jvm_root) idx := constant_pool.idx_string2(fcn) code_attribute.opcode_ldc(idx) idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_d1,fz_d2); -- forName code_attribute.opcode_invokestatic(idx,-1) idx := constant_pool.idx_string2(switch.name(run_feature)); -- the switch method name code_attribute.opcode_ldc(idx) code_attribute.opcode_push_integer(arguments_count + 1) idx := constant_pool.idx_class2(fz_java_lang_class); -- array of java/lang/Class code_attribute.opcode_anewarray(idx) create fcn.make(64) code_attribute.opcode_dup code_attribute.opcode_push_integer(0) fcn.clear fcn.append(ace.executable_name) fcn.extend('.') fcn.append(fz_jvm_root) idx := constant_pool.idx_string2(fcn) code_attribute.opcode_ldc(idx) idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_d1,fz_d2); -- forName code_attribute.opcode_invokestatic(idx,-1) code_attribute.opcode_aastore from i_argument := 1 until i_argument > arguments_count loop code_attribute.opcode_dup code_attribute.opcode_push_integer(i_argument) if arguments.expression(i_argument).result_type.is_basic_eiffel_expanded then push_jvm_expanded_argument_object_wrapper_type(run_feature.arguments.type(i_argument)) else fcn.clear fcn.append(ace.executable_name) fcn.extend('.') fcn.append(fz_jvm_root) idx := constant_pool.idx_string2(fcn) code_attribute.opcode_ldc(idx) idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_d1,fz_d2); -- forName code_attribute.opcode_invokestatic(idx,-1) end code_attribute.opcode_aastore i_argument := i_argument + 1 end idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_c6,fz_c7); -- getMethod code_attribute.opcode_invokevirtual(idx,-1) fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_method,fz_21) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1) -- open_argument_count if base /= void then open_argument_count := open_argument_count + 1 end -- open_arguments code_attribute.opcode_dup code_attribute.opcode_push_integer(open_argument_count) idx := constant_pool.idx_class2(fz_21) code_attribute.opcode_anewarray(idx) idx := constant_pool.idx_fieldref3(fcn,as_open_arguments,fz_c2) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1) -- open_argument_indices code_attribute.opcode_dup code_attribute.opcode_push_integer(open_argument_count) code_attribute.opcode_newarray(10) -- array of int fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_open_argument_indices,fz_d3) space := result_type.jvm_stack_space code_attribute.opcode_putfield(idx,space + 1); -- store open_argument_indices -- open_argument_indices contents code_attribute.opcode_dup fcn := result_type.run_class.fully_qualified_name idx := constant_pool.idx_fieldref3(fcn,as_open_argument_indices,fz_d3) space := result_type.jvm_stack_space code_attribute.opcode_getfield(idx,space + 1); -- get open_argument_indices i_open_argument := 0 if base /= void then code_attribute.opcode_dup code_attribute.opcode_push_integer(i_open_argument) code_attribute.opcode_push_integer(0) code_attribute.opcode_iastore i_open_argument := 1 end from i_argument := 1 until i_argument > arguments_count loop if not is_closed_argument(i_argument) then code_attribute.opcode_dup code_attribute.opcode_push_integer(i_open_argument) code_attribute.opcode_push_integer(i_argument) code_attribute.opcode_iastore i_open_argument := i_open_argument + 1 end i_argument := i_argument + 1 end code_attribute.opcode_pop end end push_jvm_expanded_argument_to_object_wrapper(arg_expression: EXPRESSION; f_type: E_TYPE) is local idx: INTEGER space: INTEGER do if f_type.is_boolean then idx := constant_pool.idx_class2(fz_java_lang_boolean) code_attribute.opcode_new(idx) code_attribute.opcode_dup space := arg_expression.standard_compile_to_jvm_into(f_type) idx := constant_pool.idx_methodref3(fz_java_lang_boolean,fz_35,fz_cb); -- code_attribute.opcode_invokespecial(idx,-1) elseif f_type.is_character then idx := constant_pool.idx_class2(fz_java_lang_byte) code_attribute.opcode_new(idx) code_attribute.opcode_dup space := arg_expression.standard_compile_to_jvm_into(f_type) idx := constant_pool.idx_methodref3(fz_java_lang_byte,fz_35,fz_cc1); -- code_attribute.opcode_invokespecial(idx,-1) elseif f_type.is_integer then idx := constant_pool.idx_class2(fz_java_lang_integer) code_attribute.opcode_new(idx) code_attribute.opcode_dup space := arg_expression.standard_compile_to_jvm_into(f_type) idx := constant_pool.idx_methodref3(fz_java_lang_integer,fz_35,fz_27); -- code_attribute.opcode_invokespecial(idx,-1) elseif f_type.is_real then idx := constant_pool.idx_class2(fz_java_lang_float) code_attribute.opcode_new(idx) code_attribute.opcode_dup space := arg_expression.standard_compile_to_jvm_into(f_type) idx := constant_pool.idx_methodref3(fz_java_lang_float,fz_35,fz_ce); -- code_attribute.opcode_invokespecial(idx,-1) elseif f_type.is_double then idx := constant_pool.idx_class2(fz_java_lang_double) code_attribute.opcode_new(idx) code_attribute.opcode_dup space := arg_expression.standard_compile_to_jvm_into(f_type) idx := constant_pool.idx_methodref3(fz_java_lang_double,fz_35,fz_cf); -- code_attribute.opcode_invokespecial(idx,-1) elseif f_type.is_pointer then arg_expression.compile_to_jvm end end push_jvm_expanded_argument_object_wrapper_type(f_type: E_TYPE) is local idx: INTEGER; fcn: STRING do if f_type.is_boolean then idx := constant_pool.idx_fieldref3(fz_java_lang_boolean,as_type,fz_ca) code_attribute.opcode_getstatic(idx,2); -- get java.lang.Boolean.TYPE elseif f_type.is_character then idx := constant_pool.idx_fieldref3(fz_java_lang_byte,as_type,fz_ca) code_attribute.opcode_getstatic(idx,2); -- get java.lang.Byte.TYPE elseif f_type.is_integer then idx := constant_pool.idx_fieldref3(fz_java_lang_integer,as_type,fz_ca) code_attribute.opcode_getstatic(idx,2); -- get java.lang.Integer.TYPE elseif f_type.is_real then idx := constant_pool.idx_fieldref3(fz_java_lang_float,as_type,fz_ca) code_attribute.opcode_getstatic(idx,2); -- get java.lang.Float.TYPE elseif f_type.is_double then idx := constant_pool.idx_fieldref3(fz_java_lang_double,as_type,fz_ca) code_attribute.opcode_getstatic(idx,2); -- get java.lang.Double.TYPE elseif f_type.is_pointer then create fcn.make(64) fcn.copy(fz_java_lang_object) fcn.replace_all('/','.') idx := constant_pool.idx_string2(fcn) code_attribute.opcode_ldc(idx) idx := constant_pool.idx_methodref3(fz_java_lang_class,fz_d1,fz_d2); -- forName code_attribute.opcode_invokestatic(idx,-1) end end jvm_branch_if_false: INTEGER is do not_yet_implemented end jvm_branch_if_true: INTEGER is do not_yet_implemented end feature {AGENT_POOL} falling_down is do switch_collection.update_with(run_feature) end c_define_type_1(boost: BOOLEAN) is require cpp.on_h; boost = ace.boost local i, id: INTEGER; t: E_TYPE do id := se_agent_id buffer.clear buffer.append(once "typedef struct _se_agent") id.append_in(buffer) buffer.append(once " se_agent") id.append_in(buffer) buffer.append(once ";%Nstruct _se_agent") id.append_in(buffer) buffer.extend('{') if not boost then buffer.append(once "Tid id;") end buffer.append(once "int agent_id;") t := run_feature.result_type if t = void then buffer.append(fz_void) else t.c_type_for_result_in(buffer) end buffer.append(once "(*afp)(") if not boost then buffer.append(once "se_dump_stack*,") end buffer.append(once "se_agent") id.append_in(buffer) buffer.extend('*') if base /= Void then buffer.extend(',') t := run_feature.current_type t.c_type_for_result_in(buffer) end if open_args /= Void then from i := 1; until i > arguments.count loop if not is_closed_argument(i) then buffer.extend(',') t := arguments.expression(i).result_type t.c_type_for_result_in(buffer) end i := i + 1 end end buffer.append(once ");") if base = Void then t := run_feature.current_type t.c_type_for_argument_in(buffer) buffer.append(once " C;") end if arguments /= Void then from i := 1 until i > arguments.count loop if is_closed_argument(i) then t := arguments.expression(i).result_type t.c_type_for_argument_in(buffer) buffer.append(once " a") i.append_in(buffer) buffer.extend(';') end i := i + 1 end end t := run_feature.result_type if t /= Void then t.c_type_for_argument_in(buffer) buffer.append(once " R;") end buffer.append(once "};%N") cpp.put_string(buffer) ensure cpp.on_h end c_define_type_2 is require cpp.on_h local id: INTEGER do id := se_agent_id cpp.put_string(once "se_agent") cpp.put_integer(id) cpp.put_character(' ') cpp.put_character('u') cpp.put_integer(id) cpp.put_character(';') ensure cpp.on_h end c_define_function(boost: BOOLEAN) is require cpp.on_c; boost = ace.boost local t, rt: E_TYPE; i, id: INTEGER do id := se_agent_id -- The local execution function: buffer.clear buffer.append(once "%Nstatic ") t := run_feature.result_type if t /= Void then t.c_type_for_result_in(buffer) else buffer.append(fz_void) end buffer.extend(' ') buffer.append(execution_function_name) buffer.extend('(') if not boost then buffer.append(once "se_dump_stack*caller,") end buffer.append(once "se_agent") id.append_in(buffer) buffer.extend('*') buffer.extend('u') if base /= Void then buffer.extend(',') t := run_feature.current_type t.c_type_for_result_in(buffer) buffer.extend(' ') buffer.extend('C') end if open_args /= Void then from i := 1; until i > arguments.count loop if not is_closed_argument(i) then buffer.extend(',') t := arguments.expression(i).result_type t.c_type_for_result_in(buffer) buffer.extend(' ') buffer.extend('a') i.append_in(buffer) end i := i + 1 end end buffer.append(once "){%N") if base = Void then t := target.result_type if t.is_user_expanded then t.c_type_for_target_in(buffer) buffer.append(once " C=&(u->C);%N") else t.c_type_for_argument_in(buffer) buffer.append(once " C=u->C;%N") end end if arguments /= Void then from i := 1; until i > arguments.count loop if is_closed_argument(i) then t := arguments.expression(i).result_type t.c_type_for_argument_in(buffer) buffer.extend(' ') buffer.extend('a') i.append_in(buffer) buffer.append(once "=u->a") i.append_in(buffer) buffer.extend(';') buffer.extend('%N') end i := i + 1 end end cpp.put_string(buffer) if not boost then cpp.put_string( once "[ se_frame_descriptor fd={"",0,0,"",1}; se_dump_stack ds; ds.fd=&fd; ds.p=0; ds.caller=caller; ]") end -- Calling the actual one: create e_agent_call.make(Current,run_feature) rt := run_feature.result_type if rt /= Void then cpp.put_string(once "u->R=") end cpp.put_cpc(e_agent_call) if rt /= Void then cpp.put_string(once ";%Nreturn u->R;%N") end cpp.put_character('}') -- The definition function: buffer.clear buffer.append(once "/*agent*/T0*") buffer.append(definition_function_name) buffer.extend('(') if not boost then buffer.append(once "se_dump_stack*caller") end if base = Void then if buffer.last /= '(' then buffer.extend(',') end t := target.result_type t.c_type_for_argument_in(buffer) buffer.extend(' ') buffer.extend('C') end if arguments /= Void then from i := 1; until i > arguments.count loop if is_closed_argument(i) then if buffer.last /= '(' then buffer.extend(',') end t := arguments.expression(i).result_type t.c_type_for_argument_in(buffer) buffer.extend(' ') buffer.extend('a') i.append_in(buffer) end i := i + 1 end end if buffer.last = '(' then buffer.append(fz_void) end buffer.extend(')') cpp.put_c_heading(buffer) cpp.put_string(once "se_agent") cpp.put_integer(id) cpp.put_string(once "*u=(void*)new_agent(") if not boost then cpp.put_integer(result_type.id) end cpp.put_string(once ");%Nu->agent_id=") cpp.put_integer(se_agent_id) cpp.put_string(once ";%Nu->afp=") cpp.put_string(execution_function_name) cpp.put_string(once ";%N") if base = Void then cpp.put_string(once "u->C=C;%N") end if arguments /= Void then from i := 1 until i > arguments.count loop if is_closed_argument(i) then cpp.put_string(once "u->a") cpp.put_integer(i) cpp.put_string(once "=a") cpp.put_integer(i) cpp.put_string(once ";%N") end i := i + 1 end end cpp.put_string(once "return((T0*)u);%N}%N") ensure cpp.on_c end feature {OPEN_OPERAND} register(open_operand: OPEN_OPERAND) is require open_operand /= Void do if open_args = Void then create open_args.with_capacity(4) end open_args.add_last(open_operand) end feature {JVM} base: E_TYPE -- When the target itself is an open operand. call: CALL -- The one provided by the eiffel_parser. current_type: E_TYPE -- Not Void when checked in this context. target: EXPRESSION -- Computed one using `base' and `call'. run_feature: RUN_FEATURE -- Computed one using `target' and `call'. feature_name: FEATURE_NAME -- Computed one using `call'. arguments: EFFECTIVE_ARG_LIST -- Computed one using the `call'. open_args: FIXED_ARRAY[OPEN_OPERAND] -- Computed using `arguments' to store, if any, the list of open -- arguments. -- (The `target' is never part of this list, see -- `base'.) open_tuple: TYPE_TUPLE definition_function_name: STRING -- The name of the definition function. execution_function_name: STRING -- The name of the execution function. e_agent_call: E_AGENT_CALL -- The face CALL_PROC_CALL. is_closed_argument(i: INTEGER): BOOLEAN is -- Is the `i'th argument a closed argument? require i.in_range(1,arguments.count) local e: EXPRESSION; open_operand: OPEN_OPERAND do e := arguments.expression(i) open_operand ?= e Result := open_operand = Void end feature {NONE} make(sp: like start_position; b: like base; c: like call) is require not sp.is_unknown c /= Void do start_position := sp base := b call := c debug debug_info := "line " + sp.line.to_string + " " + sp.path end ensure start_position = sp base = b call = c end debug_info: STRING buffer: STRING is once create Result.make(512) end invariant call /= Void end -- E_AGENT