Code coverage for itm_read.li
///////////////////////////////////////////////////////////////////////////////
// Lisaac Compiler //
// //
// LSIIT - ULP - CNRS - INRIA - FRANCE //
// //
// This program 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 3 of the License, or //
// (at your option) any later version. //
// //
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>. //
// //
// http://isaacproject.u-strasbg.fr/ //
///////////////////////////////////////////////////////////////////////////////
Section Header
+ name := ITM_READ;
- copyright := "2003-2007 Benoit Sonntag";
- author := "Sonntag Benoit (bsonntag@loria.fr)";
- comment := "For local access variable or send message without argument";
// BSBS: Optim: Penser à faire un ITM_READ_ARG3 pour tous les `if then else'
Section Inherit
+ parent_itm_code:Expanded ITM_CODE;
Section Public
- is_affect:POSITION; // Nothing (it's good with 0).
//
// Data
//
+ name:STRING_CONSTANT;
//
// Constructor
//
- create p:POSITION name n:STRING_CONSTANT :SELF <-
( + result:SELF;
result := clone;
result.make p name n;
result
);
- make p:POSITION name n:STRING_CONSTANT <-
(
position := p;
name := n;
);
//
// Runnable
//
- to_run_expr:EXPR <-
( + result:EXPR;
+ loc:LOCAL;
loc := lookup name;
(loc != NULL).if {
//
// Local Access.
//
(loc.style = '-').if {
loc.set_ensure_count 1;
name := loc.intern_name;
result := to_run_with NULL args NULL;
} else {
result := loc.read position;
};
} else {
//
// Slot Access without argument.
//
result := to_run_with NULL args NULL;
};
result
);
//
// Display.
//
- append_in buffer:STRING <-
(
buffer.append name;
buffer.append "()";
);
Section ITM_READ, SLOT_DATA
- to_run_with first_itm:ITM_CODE args larg:FAST_ARRAY(ITM_CODE) :EXPR <-
( + rec:EXPR;
//
+ itm_list:ITM_LIST;
+ itm_read:ITM_READ;
+ is_resend,implicit_self:BOOLEAN;
//
// Compute `rec'.
//
(first_itm = NULL).if {
// Implicit Self.
rec := lookup (ALIAS_STR.variable_self).read position;
implicit_self := TRUE;
} else {
rec := first_itm.to_run_expr;
// Resend detect.
itm_list ?= first_itm;
(itm_list != NULL).if {
itm_read ?= itm_list.code.first;
} else {
itm_read ?= first_itm;
};
is_resend := (
(itm_read != NULL) &&
{position.prototype.search_parent (itm_read.name)}
);
};
to_run_with_self (rec,implicit_self,is_resend) args larg
);
- to_run_with_self (r:EXPR,implicit_self,is_resend:BOOLEAN)
args larg:FAST_ARRAY(ITM_CODE) :EXPR <-
( + args:FAST_ARRAY(EXPR);
+ rec_type:TYPE;
+ rec:EXPR;
+ em:EXPR_MULTIPLE;
+ pos_null:POSITION;
//
+ slot_msg:SLOT;
+ is_block_value:BOOLEAN;
//
+ base:NODE;
rec := r;
//
// Detect slot.
//
args := ALIAS_ARRAY(EXPR).new;
rec_type := rec.static_type.raw;
(rec_type = TYPE_VOID).if {
// BSBS: Ce cas ne doit jamais arriver !
// il se déclenche avec parent.msg.truc lorsque msg du parent n'a pas de type de retour
// Mais que le profil général en a un...
semantic_error (position,"Call on Void");
};
(
(rec_type.is_block) &&
{name = ALIAS_STR.slot_value}
).if {
// { ... }.value
is_block_value := TRUE;
} else {
slot_msg := rec_type.get_slot name;
(slot_msg = NULL).if {
string_tmp.copy "Slot `";
string_tmp.append name;
string_tmp.append "' not found in `";
rec_type.append_name_in string_tmp;
string_tmp.append "'.";
semantic_error (position,string_tmp);
};
// Verification
(verify).if {
(
((larg = NULL) && {slot_msg.argument_list.count != 1}) ||
{(larg != NULL) && {larg.count != slot_msg.argument_list.count-1}}
).if {
POSITION.put_error semantic text "Incorrect number argument.";
slot_msg.position.put_position;
position.put_position;
POSITION.send_error;
};
last_position := slot_msg.position;
(
(profil_slot != NULL) &&
{! slot_msg.id_section.access rec_type with (profil_slot.type_self.raw)}
).if {
string_tmp.copy "Type ";
profil_slot.type_self.append_name_in string_tmp;
string_tmp.append " does not have access to this slot.";
POSITION.put_error warning text string_tmp;
slot_msg.position.put_position;
position.put_position;
POSITION.send_error;
};
last_position := pos_null;
};
};
//
// Add arguments
//
add_arg rec to 0 in args for slot_msg block is_block_value;
em ?= rec;
(em != NULL).if {
rec := em.expr_list.first;
};
(larg != NULL).if {
(larg.lower).to (larg.upper) do { j:INTEGER;
add_arg (larg.item j.to_run_expr) to (j+1) in args for slot_msg block is_block_value;
};
};
//
// Send message.
//
(is_block_value).if {
// { ... }.value
args := ALIAS_ARRAY(EXPR).copy args;
args.put (args.first.my_copy) to 0;
//rec := slot_msg.slot_data_intern.read position with rec;
base := NODE.new_block position receiver rec with args;
}.elseif {args.count = 1} then {
// Classic message without arguments.
(is_resend).if {
args.put (lookup (ALIAS_STR.variable_self).read position) to 0;
args.first.remove;
};
((verify) && {is_all_warning} && {name == "deferred"}).if {
string_tmp.copy "Deferred in `";
profil_slot.slot.pretty_name_in string_tmp;
string_tmp.append "' for ";
rec.static_type.append_name_in string_tmp;
warning_error (position,string_tmp);
};
base := NODE.new_read position slot slot_msg
receiver rec self (args.first) intern implicit_self;
ALIAS_ARRAY(EXPR).free args;
} else {
// Classic message with arguments.
(is_resend).if {
args.put (lookup (ALIAS_STR.variable_self).read position) to 0;
} else {
args.put (args.first.my_copy) to 0;
};
args := ALIAS_ARRAY(EXPR).copy args;
base := NODE.new_read position slot slot_msg
receiver rec with args intern implicit_self;
};
list_current.add_last base;
(larg != NULL).if {
ALIAS_ARRAY(ITM_CODE).free larg;
};
? {base.result_expr != NULL};
base.result_expr
);
Section Private
- add_arg e:EXPR to idx:INTEGER
in args:FAST_ARRAY(EXPR) for slot:SLOT block is_block_value:BOOLEAN <-
( + em:EXPR_MULTIPLE;
+ count:INTEGER;
+ itm_arg:ITM_ARGUMENT;
+ ts:ITM_TYPE_SIMPLE;
+ t:TYPE_FULL;
+ ex:EXPR;
em ?= e;
(em != NULL).if {
count := em.cardinality;
args.append_collection (em.expr_list);
} else {
count := 1;
args.add_last e;
};
(verify).if {
(! is_block_value).if {
itm_arg := slot.argument_list.item idx;
(itm_arg.count != count).if {
string_tmp.copy "Incorrect vector size for #";
idx.append_in string_tmp;
string_tmp.append " argument of `";
string_tmp.append name;
string_tmp.append "' slot. (slot #";
itm_arg.count.append_in string_tmp;
string_tmp.append ", call #";
count.append_in string_tmp;
string_tmp.add_last ')';
POSITION.put_error semantic text string_tmp;
itm_arg.position.put_position;
e.position.put_position;
POSITION.send_error;
};
(args.count > 1).if {
(itm_arg.lower).to (itm_arg.upper) do { i:INTEGER;
ts ?= itm_arg.item i;
((ts != NULL) && {ts = ITM_TYPE_SIMPLE.type_self}).if {
ex := args.item (args.upper - itm_arg.upper + i);
t := ex.static_type;
((! t.is_expanded) && {! t.is_strict}).if {
string_tmp.copy "Type expression (";
t.append_name_in string_tmp;
string_tmp.append ") is not Expanded or Strict for SELF argument type.";
POSITION.put_error semantic text string_tmp;
itm_arg.position.put_position;
ex.position.put_position;
position.put_position;
POSITION.send_error;
};
};
};
};
}.elseif {(idx = 0) && {count != 1}} then {
semantic_error (e.position,"Incorrect vector size for `value' message.");
};
};
);