home *** CD-ROM | disk | FTP | other *** search
- -- This file is part of SmallEiffel The GNU Eiffel Compiler.
- -- Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
- -- Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
- -- http://www.loria.fr/SmallEiffel
- -- SmallEiffel 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. SmallEiffel 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 SmallEiffel; 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_WHEN
- --
- -- To store a when clause of an inspect instruction.
- --
-
- inherit GLOBALS;
-
- creation {EIFFEL_PARSER}
- make
-
- creation {E_WHEN,WHEN_LIST}
- from_e_when
-
- feature
-
- start_position: POSITION;
- -- Of the first character of keyword "when".
-
- feature {E_WHEN}
-
- list: ARRAY[WHEN_ITEM];
-
- feature
-
- header_comment: COMMENT;
- -- Of the when clause.
-
- compound: COMPOUND;
- -- Of the when clause if any.
-
- when_list: WHEN_LIST;
- -- Corresponding one when checked.
-
- values: ARRAY[BOOLEAN];
- -- True when the corresponding index is in the when.
-
- feature {NONE}
-
- points1: FIXED_ARRAY[INTEGER] is
- -- To reach the `compound'.
- once
- !!Result.with_capacity(12);
- end;
-
- point2: INTEGER;
- -- To go outside the E_INSPECT.
-
- feature {EIFFEL_PARSER}
-
- make(sp: like start_position; hc: like header_comment) is
- require
- sp /= Void
- do
- start_position := sp;
- header_comment := hc;
- ensure
- start_position = sp;
- end;
-
- feature {WHEN_LIST}
-
- afd_check is
- do
- if compound /= Void then
- compound.afd_check;
- end;
- end;
-
- feature {NONE}
-
- from_e_when(other: like Current) is
- local
- i: INTEGER;
- when_item: WHEN_ITEM;
- do
- start_position := other.start_position;
- list := other.list.twin;
- from
- i := list.lower;
- until
- i > list.upper
- loop
- when_item := list.item(i).twin;
- when_item.clear_e_when;
- list.put(when_item,i);
- i := i + 1;
- end;
- header_comment := other.header_comment;
- compound := other.compound;
- end;
-
- feature
-
- use_current: BOOLEAN is
- do
- if compound /= Void then
- Result := compound.use_current;
- end;
- end;
-
- current_type: TYPE is
- require
- when_list /= Void
- do
- Result := when_list.current_type;
- end;
-
- e_inspect: E_INSPECT is
- do
- Result := when_list.e_inspect;
- end;
-
- feature {WHEN_LIST}
-
- compile_to_jvm(else_position: POSITION; remainder: INTEGER) is
- -- Where `remainder' is the number of E_WHEN after Current.
- local
- point3, point4, bi, bs: INTEGER;
- must_test: BOOLEAN;
- ca: like code_attribute;
- do
- ca := code_attribute;
- if remainder > 0 then
- must_test := true;
- elseif run_control.no_check then
- must_test := true;
- else -- boost :
- must_test := else_position /= Void;
- end;
- points1.clear;
- if must_test then
- from
- bi := values.lower;
- until
- bi > values.upper
- loop
- from
- bs := bi + 1;
- until
- bs > values.upper or else not values.item(bs)
- loop
- bs := bs + 1;
- end;
- bs := bs - 1;
- --
- if bi = bs then
- ca.opcode_dup;
- ca.opcode_push_integer(bi);
- points1.add_last(ca.opcode_if_icmpeq);
- else
- ca.opcode_dup;
- ca.opcode_push_integer(bi);
- point3 := ca.opcode_if_icmplt;
- ca.opcode_dup;
- ca.opcode_push_integer(bs);
- points1.add_last(ca.opcode_if_icmple);
- ca.resolve_u2_branch(point3);
- end;
- from
- bi := bs + 1;
- until
- bi > values.upper or else values.item(bi)
- loop
- bi := bi + 1;
- end;
- end;
- point4 := ca.opcode_goto;
- end;
- ca.resolve_with(points1);
- if compound /= Void then
- compound.compile_to_jvm;
- end;
- point2 := ca.opcode_goto;
- if must_test then
- ca.resolve_u2_branch(point4);
- end;
- end;
-
- compile_to_jvm_resolve_branch is
- do
- code_attribute.resolve_u2_branch(point2);
- end;
-
- compile_to_c is
- local
- bi, bs: INTEGER;
- do
- cpp.put_string("%Nif(");
- from
- bi := values.lower;
- until
- bi > values.upper
- loop
- from
- bs := bi + 1;
- until
- bs > values.upper or else not values.item(bs)
- loop
- bs := bs + 1;
- end;
- bs := bs - 1;
- --
- cpp.put_character('(');
- if bi = bs then
- cpp.put_integer(bi);
- cpp.put_string("==");
- cpp.put_inspect;
- else
- cpp.put_character('(');
- cpp.put_integer(bi);
- cpp.put_string("<=");
- cpp.put_inspect;
- cpp.put_string(")&&(");
- cpp.put_inspect;
- cpp.put_string("<=");
- cpp.put_integer(bs);
- cpp.put_character(')');
- end;
- cpp.put_character(')');
- --
- from
- bi := bs + 1;
- until
- bi > values.upper or else values.item(bi)
- loop
- bi := bi + 1;
- end;
- if bi <= values.upper then
- cpp.put_string("||");
- end;
- end;
- cpp.put_string("){%N");
- if compound /= Void then
- compound.compile_to_c;
- end;
- cpp.put_string(fz_12);
- end;
-
- pretty_print is
- local
- i: INTEGER;
- do
- fmt.keyword(fz_when);
- fmt.level_incr;
- if header_comment /= Void then
- header_comment.pretty_print;
- end;
- if list /= Void then
- from
- i := list.lower;
- until
- i > list.upper
- loop
- list.item(i).pretty_print;
- i := i + 1;
- if i <= list.upper then
- fmt.put_character(',');
- end;
- end;
- end;
- fmt.level_decr;
- fmt.keyword(fz_then);
- fmt.level_incr;
- if compound /= Void then
- compound.pretty_print;
- end;
- fmt.level_decr;
- end;
-
- includes_integer(v: INTEGER): BOOLEAN is
- do
- Result := ((values /= Void) and then
- values.valid_index(v) and then
- values.item(v));
- end;
-
- feature {WHEN_LIST,E_WHEN}
-
- to_runnable_integer(wl: like when_list): like Current is
- require
- wl /= Void;
- local
- ne, i: INTEGER;
- when_item: WHEN_ITEM;
- do
- if when_list = Void then
- ne := nb_errors;
- when_list := wl;
- if list = Void then
- eh.add_position(e_inspect.start_position);
- error(start_position,em2);
- else
- from
- i := list.lower;
- until
- i > list.upper or else nb_errors - ne > 0
- loop
- when_item := list.item(i).to_runnable_integer(Current);
- if when_item = Void then
- error(start_position,em1);
- else
- list.put(when_item,i);
- end;
- i := i + 1;
- end;
- end;
- if compound /= Void then
- compound := compound.to_runnable(current_type);
- if compound = Void then
- error(start_position,em1);
- end;
- end;
- Result := Current;
- else
- !!Result.from_e_when(Current);
- Result := Result.to_runnable_integer(wl);
- end;
- ensure
- Result.when_list = wl
- end;
-
- to_runnable_character(wl: like when_list): like Current is
- require
- wl /= Void;
- local
- ne, i: INTEGER;
- when_item: WHEN_ITEM;
- do
- if when_list = Void then
- ne := nb_errors;
- when_list := wl;
- if list = Void then
- eh.add_position(e_inspect.start_position);
- error(start_position,em2);
- else
- from
- i := list.lower;
- until
- i > list.upper or else nb_errors - ne > 0
- loop
- when_item := list.item(i).to_runnable_character(Current);
- if when_item = Void then
- error(start_position,em1);
- else
- list.put(when_item,i);
- end;
- i := i + 1;
- end;
- end;
- if compound /= Void then
- compound := compound.to_runnable(current_type);
- if compound = Void then
- error(start_position,em1);
- end;
- end;
- Result := Current;
- else
- !!Result.from_e_when(Current);
- Result := Result.to_runnable_character(wl);
- end;
- ensure
- Result.when_list = wl
- end;
-
- feature {WHEN_ITEM_1}
-
- add_when_item_1(wi1: WHEN_ITEM_1) is
- require
- wi1 /= Void
- local
- v: INTEGER;
- do
- v := wi1.expression_value;
- if e_inspect.includes(v) then
- err_occ(v,wi1.start_position);
- elseif values = Void then
- !!values.make(v,v);
- values.put(true,v);
- else
- values.force(true,v);
- end;
- ensure
- e_inspect.includes(wi1.expression_value);
- end;
-
- feature {WHEN_ITEM_2}
-
- add_when_item_2(wi2: WHEN_ITEM_2) is
- require
- wi2 /= Void
- local
- l, u, i: INTEGER;
- do
- l := wi2.lower_value;
- u := wi2.upper_value;
- if l >= u then
- error(wi2.start_position,"Not a good slice.");
- end;
- if nb_errors = 0 then
- from
- i := l;
- until
- i > u
- loop
- if e_inspect.includes(i) then
- err_occ(i,wi2.start_position);
- i := u + 1;
- else
- i := i + 1;
- end;
- end;
- end;
- if nb_errors = 0 then
- if values = Void then
- !!values.make(l,u);
- values.set_all_with(true);
- else
- values.force(true,l);
- values.force(true,u);
- values.set_slice_with(true,l,u);
- end;
- end;
- end;
-
- feature {EIFFEL_PARSER}
-
- add_value(v: EXPRESSION) is
- require
- v /= Void;
- local
- element: WHEN_ITEM_1
- do
- !!element.make(v);
- if list = Void then
- list := <<element>>;
- else
- list.add_last(element);
- end;
- end;
-
- add_slice(min, max: EXPRESSION) is
- require
- min /= Void;
- max /= Void;
- local
- element: WHEN_ITEM_2;
- do
- !!element.make(min,max);
- if list = Void then
- list := <<element>>;
- else
- list.add_last(element);
- end;
- end;
-
- set_compound(c: like compound) is
- do
- compound := c;
- ensure
- compound = c
- end;
-
- feature {NONE}
-
- err_occ(v: INTEGER; p: POSITION) is
- do
- eh.add_position(e_inspect.start_position);
- eh.append("Second occurrence for this value (");
- eh.append(v.to_string);
- error(p,") in the same inspect.");
- end;
-
- feature {NONE}
-
- em1: STRING is "Bad when clause.";
- em2: STRING is "Empty when clause in inspect.";
-
- end -- E_WHEN
-
-
-