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.");
      }
;
    }
;
  )
;