/*     
      BYTE CODE INTERPRETER . Magma 1.0 . 1996 . Sylvain HUET

         readmagv.cpp : module magma du loader de packages (calcul variables)
*/
// Modification history:
//
//$ FA(19/04/2001): Promote file to C++. Rename from readmagv.c to readmagv.cpp
//$ FA(03/05/2001): Use new lexer interface (lexer.h)
//$ FA(04/05/2001): Accept floating-point literals (including negative literals)
//$ FA(17/07/2001): Use lexer utility function a2i() as a replacement of Mgetnum()
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lexer.h"
extern "C" {
#include "mmemory.h"
#include "mbytec2.h"   // for the declaration of MBdeftab()
#include "listlab.h"   // for the declaration of Mpushstrtok()
}


int PKreadvt(mmachine m,manlyz z,int ind);

/* lecture d'une Expression Variable [L'] (le premier crochet a ete lu) */
int PKreadvtab(mmachine m,manlyz z,int ind)
{
  int k,n,q;

  n=0;
  q=1;
  while(q)
    {
      if (Mreadtok(z))
        {
          sprintf(z->mess,"missing element");
          return MERRTYP;
        }
      if (z->tok[0]==']') q=0;
      else
        {
          if (k=PKreadvt(m,z,ind)) return k;
          n++;
        }
    }
  if (MMpush(m,n*2)) return MERRMEM;
  return MBdeftab(m);
}

/* lecture d'une Expression V2 */
int PKreadv2(mmachine m,manlyz z,int ind)
{
  int i,k;

//$ FA(04/05/2001): Accept floating-point literals
  if (z->lex.current().kind() == Token::kInt) {
    a2i(z->lex.current().lexeme(), &i); //$ FA(17/07/2001)
    return MMpush(m, i<<1);
  }
  if (z->lex.current().kind() == Token::kFloat) {
    float f = (float)atof(z->lex.current().lexeme());
    return MMpush(m, (*(int32*)&f)&0xfffffffe);
  }
//
  if (!strcmp(z->tok,"-")) {
    if (Mreadtok(z)) return MERRTYP;
    if (!a2i(z->tok, &i))               //$ FA(17/07/2001)
      return MERRTYP;
    return MMpush(m,-i*2);
  }
//$ FA(04/05/2001): Accept negative floating-point literals
  if (!strcmp(z->tok, "-.")) {
    if (Mreadtok(z) || z->lex.current().kind() != Token::kFloat) 
      return MERRTYP;
    float f = -(float)atof(z->lex.current().lexeme());
    return MMpush(m, (*(int32*)&f)&0xfffffffe);
  }
//
  if (z->tok[0]=='\'')
    {
      //if (Mreadtok(z)) return MERRTYP;
      //i=(z->tok[0])&255;
      i = z->tok[1]&0xff;
      return MMpush(m,i*2);
    }
  if (!strcmp(z->tok,"nil")) return MMpush(m,NIL);
      
  if (z->tok[0]=='\"') return Mpushstrtok(m,z->tok);

  if (z->tok[0]=='[') return PKreadvtab(m,z,ind);

  if (z->tok[0]=='(')
    {
      if (Mreadtok(z)) return 0;
      if (k=PKreadvt(m,z,ind)) return k;
      if ((Mreadtok(z))||(z->tok[0]!=')'))
        {
          sprintf(z->mess,") expected");
          return MERRTYP;
        }
      return 0;
    }

  sprintf(z->mess,"component of variable expected");
  return MERRTYP;
}

/* lecture d'une Expression V1 */
int PKreadvt(mmachine m,manlyz z,int ind)
{
  int k;

  if (k=PKreadv2(m,z,ind)) return k;
  if (Mreadtok(z)) return 0;
  if (strcmp(z->tok,"::"))
    {
      z->giveback=1;
      return 0;
    }
  if (Mreadtok(z))
    {
      sprintf(z->mess,"expression expected");
      return MERRTYP;
    }
  if (k=PKreadvt(m,z,ind)) return k;
  if (MMpush(m,2*2)) return MERRMEM;
  if (k=MBdeftab(m)) return k;
  return 0;
}

