Example #1
0
static void lll_forprep (lua_State *L, TValue *ra)
{
    TValue *init = ra;
    TValue *plimit = ra + 1;
    TValue *pstep = ra + 2;
    lua_Integer ilimit;
    int stopnow;
    if (ttisinteger(init) && ttisinteger(pstep) &&
        forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
      /* all values are integer */
      lua_Integer initv = (stopnow ? 0 : ivalue(init));
      setivalue(plimit, ilimit);
      setivalue(init, initv - ivalue(pstep));
    }
    else {  /* try making all values floats */
      lua_Number ninit; lua_Number nlimit; lua_Number nstep;
      if (!tonumber(plimit, &nlimit))
        luaG_runerror(L, "'for' limit must be a number");
      setfltvalue(plimit, nlimit);
      if (!tonumber(pstep, &nstep))
        luaG_runerror(L, "'for' step must be a number");
      setfltvalue(pstep, nstep);
      if (!tonumber(init, &ninit))
        luaG_runerror(L, "'for' initial value must be a number");
      setfltvalue(init, luai_numsub(L, ninit, nstep));
    }
}
Example #2
0
/*
** Main operation less than; return 'l < r'.
*/
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
  int res;
#ifndef _KERNEL
  if (ttisnumber(l) && ttisnumber(r))  /* both operands are numbers? */
    return LTnum(l, r);
#else /* _KERNEL */
  if (ttisinteger(l) && ttisinteger(r))  /* both operands are integers? */
    return (ivalue(l) < ivalue(r));
#endif /* _KERNEL */
  else if (ttisstring(l) && ttisstring(r))  /* both are strings? */
    return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
  else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0)  /* no metamethod? */
    luaG_ordererror(L, l, r);  /* error */
  return res;
}
Example #3
0
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
                 TValue *res) {
  switch (op) {
    case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
    case LUA_OPSHL: case LUA_OPSHR:
    case LUA_OPBNOT: {  /* operate only on integers */
      lua_Integer i1; lua_Integer i2;
      if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
        setivalue(res, intarith(L, op, i1, i2));
        return;
      }
      else break;  /* go to the end */
    }
#ifndef _KERNEL
    case LUA_OPDIV: case LUA_OPPOW: {  /* operate only on floats */
      lua_Number n1; lua_Number n2;
      if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
        setfltvalue(res, numarith(L, op, n1, n2));
        return;
      }
      else break;  /* go to the end */
    }
#endif
    default: {  /* other operations */
#ifndef _KERNEL
      lua_Number n1; lua_Number n2;
      if (ttisinteger(p1) && ttisinteger(p2)) {
        setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
        return;
      }
      else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
        setfltvalue(res, numarith(L, op, n1, n2));
        return;
      }
#else /* _KERNEL */
      lua_Integer i1; lua_Integer i2;
      if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
        setivalue(res, intarith(L, op, i1, i2));
        return;
      }
#endif
      else break;  /* go to the end */
    }
  }
  /* could not perform raw operation; try metamethod */
  lua_assert(L != NULL);  /* should not fail when folding (compile time) */
  luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
}
Example #4
0
File: llex.c Project: bcrist/lua
/*
** this function is quite liberal in what it accepts, as 'luaO_str2num'
** will reject ill-formed numerals.
*/
static int read_numeral (LexState *ls, SemInfo *seminfo) {
  TValue obj;
  const char *expo = "Ee";
  int first = ls->current;
  lua_assert(lisdigit(ls->current));
  save_and_next(ls);
  if (first == '0' && check_next2(ls, "xX"))  /* hexadecimal? */
    expo = "Pp";
  for (;;) {
    if (check_next2(ls, expo))  /* exponent part? */
      check_next2(ls, "-+");  /* optional exponent sign */
    if (lisxdigit(ls->current))
      save_and_next(ls);
    else if (ls->current == '.')
      save_and_next(ls);
    else break;
  }
  save(ls, '\0');
  if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0)  /* format error? */
    lexerror(ls, "malformed number", TK_FLT);
  if (ttisinteger(&obj)) {
    seminfo->i = ivalue(&obj);
    return TK_INT;
  }
  else {
    lua_assert(ttisfloat(&obj));
    seminfo->r = fltvalue(&obj);
    return TK_FLT;
  }
}
Example #5
0
/*
** Add constant 'v' to prototype's list of constants (field 'k').
** Use scanner's table to cache position of constants in constant list
** and try to reuse constants. Because some values should not be used
** as keys (nil cannot be a key, integer keys can collapse with float
** keys), the caller must provide a useful 'key' for indexing the cache.
*/
static int addk (FuncState *fs, TValue *key, TValue *v) {
  lua_State *L = fs->ls->L;
  Proto *f = fs->f;
  TValue *idx = luaH_set(L, fs->ls->h, key);  /* index scanner table */
  int k, oldsize;
  if (ttisinteger(idx)) {  /* is there an index there? */
    k = cast_int(ivalue(idx));
    /* correct value? (warning: must distinguish floats from integers!) */
    if (k < fs->nk && ttype(&f->k[k]) == ttype(v) &&
                      luaV_rawequalobj(&f->k[k], v))
      return k;  /* reuse index */
  }
  /* constant not found; create a new entry */
  oldsize = f->sizek;
  k = fs->nk;
  /* numerical value does not need GC barrier;
     table has no metatable, so it does not need to invalidate cache */
  setivalue(idx, k);
  luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
  while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
  setobj(L, &f->k[k], v);
  fs->nk++;
  luaC_barrier(L, f, v);
  return k;
}
Example #6
0
/*
** this function is quite liberal in what it accepts, as 'luaO_str2num'
** will reject ill-formed numerals.
*/
static int read_numeral (LexState *ls, SemInfo *seminfo) {
  TValue obj;
  const char *expo = "Ee";
  int first = ls->current;
  lua_assert(lisdigit(ls->current));
  save_and_next(ls);
  if (first == '0' && check_next2(ls, "xX"))  /* hexadecimal? */
    expo = "Pp";
  for (;;) {
    if (check_next2(ls, expo))  /* exponent part? */
      check_next2(ls, "-+");  /* optional exponent sign */
    if (lisxdigit(ls->current))
      save_and_next(ls);
    else if (ls->current == '.')
      save_and_next(ls);
    else break;
  }
  save(ls, '\0');
  buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
  if (!buff2num(ls->buff, &obj))  /* format error? */
    trydecpoint(ls, &obj); /* try to update decimal point separator */
  if (ttisinteger(&obj)) {
    seminfo->i = ivalue(&obj);
    return TK_INT;
  }
  else {
    lua_assert(ttisfloat(&obj));
    seminfo->r = fltvalue(&obj);
    return TK_FLT;
  }
}
Example #7
0
/*
** Return 'l <= r', for numbers.
*/
static int LEnum (const TValue *l, const TValue *r) {
  if (ttisinteger(l)) {
    lua_Integer li = ivalue(l);
    if (ttisinteger(r))
      return li <= ivalue(r);  /* both are integers */
    else  /* 'l' is int and 'r' is float */
      return LEintfloat(li, fltvalue(r));  /* l <= r ? */
  }
  else {
    lua_Number lf = fltvalue(l);  /* 'l' must be float */
    if (ttisfloat(r))
      return luai_numle(lf, fltvalue(r));  /* both are float */
    else if (luai_numisnan(lf))  /* 'r' is int and 'l' is float */
      return 0;  /*  NaN <= i is always false */
    else  /* without NaN, (l <= r)  <-->  not(r < l) */
      return !LTintfloat(ivalue(r), lf);  /* not (r < l) ? */
  }
}
Example #8
0
/*
** return false if folding can raise an error
*/
static int validop (int op, TValue *v1, TValue *v2) {
  lua_Number a, b;
  lua_Integer i;
  cast_void(a); cast_void(b);  /* macro may not use its arguments */
  if (luai_numinvalidop(op, (cast_void(tonumber(v1, &a)), a),
                            (cast_void(tonumber(v2, &b)), b)))
    return 0;
  switch (op) {
    case LUA_OPIDIV:  /* division by 0 and conversion errors */
      return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0);
    case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
    case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT:  /* conversion errors */
      return (tointeger(v1, &i) && tointeger(v2, &i));
    case LUA_OPMOD:  /* integer module by 0 */
      return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0);
    default: return 1;  /* everything else is valid */
  }
}
Example #9
0
/*
** try to convert a non-integer value to an integer
*/
int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
  lua_Number n;
  lua_assert(!ttisinteger(obj));
  if (tonumber(obj, &n)) {
    n = l_floor(n);
    return luaV_numtointeger(n, p);
  }
  else return 0;
}
Example #10
0
int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
  lua_assert(!ttisfloat(obj));
  if (ttisinteger(obj)) {
    *n = cast_num(ivalue(obj));
    return 1;
  }
  else
    return (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, n));
}
Example #11
0
/*
** Similar to 'tonumber', but does not attempt to convert strings and
** ensure correct precision (no extra bits). Used in comparisons.
*/
static int tofloat (const TValue *obj, lua_Number *n) {
  if (ttisfloat(obj)) *n = fltvalue(obj);
  else if (ttisinteger(obj)) {
    volatile lua_Number x = cast_num(ivalue(obj));  /* avoid extra precision */
    *n = x;
  }
  else {
    *n = 0;  /* to avoid warnings */
    return 0;
  }
  return 1;
}
Example #12
0
/*
** Main operation less than or equal to; return 'l <= r'. If it needs
** a metamethod and there is no '__le', try '__lt', based on
** l <= r iff !(r < l) (assuming a total order). If the metamethod
** yields during this substitution, the continuation has to know
** about it (to negate the result of r<l); bit CIST_LEQ in the call
** status keeps that information.
*/
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
  int res;
#ifndef _KERNEL
  if (ttisnumber(l) && ttisnumber(r))  /* both operands are numbers? */
    return LEnum(l, r);
#else /* _KERNEL */
  if (ttisinteger(l) && ttisinteger(r))  /* both operands are integers? */
    return (ivalue(l) <= ivalue(r));
#endif /* _KERNEL */
  else if (ttisstring(l) && ttisstring(r))  /* both are strings? */
    return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
  else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0)  /* try 'le' */
    return res;
  else {  /* try 'lt': */
    L->ci->callstatus |= CIST_LEQ;  /* mark it is doing 'lt' for 'le' */
    res = luaT_callorderTM(L, r, l, TM_LT);
    L->ci->callstatus ^= CIST_LEQ;  /* clear mark */
    if (res < 0)
      luaG_ordererror(L, l, r);
    return !res;  /* result is negated */
  }
}
Example #13
0
/*
** Try to convert a value to a float. The float case is already handled
** by the macro 'tonumber'.
*/
int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
    TValue v;
    if (ttisinteger(obj)) {
        *n = cast_num(ivalue(obj));
        return 1;
    }
    else if (cvt2num(obj) &&    /* string convertible to number? */
      luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
        *n = nvalue(&v);    /* convert result of 'luaO_str2num' to a float */
        return 1;
    }
    else
        return 0;    /* conversion failed */
}
Example #14
0
/*
** returns the index of a 'key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The
** beginning of a traversal is signaled by 0.
*/
static unsigned int findindex (lua_State *L, Table *t, TValue *key,
                               unsigned int asize) {
  unsigned int i;
  if (ttisnil(key)) return 0;  /* first iteration */
  i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
  if (i != 0 && i <= asize)  /* is 'key' inside array part? */
    return i;  /* yes; that's the index */
  else {
    const TValue *n = getgeneric(t, key);
    if (unlikely(isabstkey(n)))
      luaG_runerror(L, "invalid key to 'next'");  /* key not found */
    i = cast_int(nodefromval(n) - gnode(t, 0));  /* key index in hash table */
    /* hash elements are numbered after array ones */
    return (i + 1) + asize;
  }
}
Example #15
0
/*
** Try to convert a value to a float. Check 'isinteger' first, because
** in general the float case is already handled by the macro 'tonumber'.
*/
int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
  TValue v;
 again:
  if (ttisinteger(obj)) {
    *n = cast_num(ivalue(obj));
    return 1;
  }
  else if (ttisfloat(obj)) {
    *n = fltvalue(obj);
    return 1;
  }
  else if (cvt2num(obj) &&  /* string convertible to number? */
            luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
    obj = &v;
    goto again;  /* convert result from 'luaO_str2num' to a float */
  }
  return 0;  /* conversion failed */
}
Example #16
0
/*
** Try to "constant-fold" an operation; return 1 iff successful
*/
static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) {
  TValue v1, v2, res;
  if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2))
    return 0;  /* non-numeric operands or not safe to fold */
  luaO_arith(fs->ls->L, op, &v1, &v2, &res);
  if (ttisinteger(&res)) {
    e1->k = VKINT;
    e1->u.ival = ivalue(&res);
  }
  else {
    lua_Number n = fltvalue(&res);
    if (luai_numisnan(n) || isminuszero(n))
      return 0;  /* folds neither NaN nor -0 */
    e1->k = VKFLT;
    e1->u.nval = n;
  }
  return 1;
}
Example #17
0
static int read_numeral (LexState *ls, SemInfo *seminfo) {
  TValue obj;
  int first = ls->current;
  lua_assert(lisdigit(ls->current));
  save_and_next(ls);
  if (first == '0')
    check_next2(ls, "xX");  /* hexadecimal? */
  for (;;) {
    if (lisxdigit(ls->current))
      save_and_next(ls);
    else break;
  }
  save(ls, '\0');
  if (!buff2num(ls->buff, &obj))  /* format error? */
    lexerror(ls, "malformed number", TK_INT);
  lua_assert(ttisinteger(&obj));
  seminfo->i = ivalue(&obj);
  return TK_INT;
}
Example #18
0
int luaV_tostring (lua_State *L, StkId obj) {
  if (!ttisnumber(obj))
    return 0;
  else {
    char buff[MAXNUMBER2STR];
    size_t len;
    if (ttisinteger(obj))
      len = lua_integer2str(buff, ivalue(obj));
    else {
      len = lua_number2str(buff, fltvalue(obj));
      if (strspn(buff, "-0123456789") == len) {  /* look like an integer? */
        buff[len++] = '.';  /* add a '.0' */
        buff[len++] = '0';
        buff[len] = '\0';
      }
    }
    setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
    return 1;
  }
}
Example #19
0
/*
** try to convert a value to an integer, rounding according to 'mode':
** mode == 0: accepts only integral values
** mode == 1: takes the floor of the number
** mode == 2: takes the ceil of the number
*/
int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
    TValue v;
 again:
    if (ttisfloat(obj)) {
        lua_Number n = fltvalue(obj);
        lua_Number f = l_floor(n);
        if (n != f) {    /* not an integral value? */
            if (mode == 0) return 0;    /* fails if mode demands integral value */
            else if (mode > 1)    /* needs ceil? */
                f += 1;    /* convert floor to ceil (remember: n != f) */
        }
        return lua_numbertointeger(f, p);
    }
    else if (ttisinteger(obj)) {
        *p = ivalue(obj);
        return 1;
    }
    else if (cvt2num(obj) &&
                        luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
        obj = &v;
        goto again;    /* convert result from 'luaO_str2num' to an integer */
    }
    return 0;    /* conversion failed */
}
Example #20
0
LUA_API int lua_isinteger (lua_State *L, int idx) {
  StkId o = index2addr(L, idx);
  return ttisinteger(o);
}
Example #21
0
/*
** try to convert a value to an integer, rounding according to 'mode':
** mode == 0: accepts only integral values
** mode == 1: takes the floor of the number
** mode == 2: takes the ceil of the number
*/
int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
  TValue v;
 again:
#ifndef _KERNEL
  if (ttisfloat(obj)) {
    lua_Number n = fltvalue(obj);
    lua_Number f = l_floor(n);
    if (n != f) {  /* not an integral value? */
      if (mode == 0) return 0;  /* fails if mode demands integral value */
      else if (mode > 1)  /* needs ceil? */
        f += 1;  /* convert floor to ceil (remember: n != f) */
    }
    return lua_numbertointeger(f, p);
  }
  else if (ttisinteger(obj)) {
#else /* _KERNEL */
  if (ttisinteger(obj)) {
    UNUSED(mode);
#endif
    *p = ivalue(obj);
    return 1;
  }
  else if (cvt2num(obj) &&
            luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
    obj = &v;
    goto again;  /* convert result from 'luaO_str2num' to an integer */
  }
  return 0;  /* conversion failed */
}


#ifndef _KERNEL
/*
** Try to convert a 'for' limit to an integer, preserving the
** semantics of the loop.
** (The following explanation assumes a non-negative step; it is valid
** for negative steps mutatis mutandis.)
** If the limit can be converted to an integer, rounding down, that is
** it.
** Otherwise, check whether the limit can be converted to a number.  If
** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
** which means no limit.  If the number is too negative, the loop
** should not run, because any initial integer value is larger than the
** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects
** the extreme case when the initial value is LUA_MININTEGER, in which
** case the LUA_MININTEGER limit would still run the loop once.
*/
static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
                     int *stopnow) {
  *stopnow = 0;  /* usually, let loops run */
  if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) {  /* not fit in integer? */
    lua_Number n;  /* try to convert to float */
    if (!tonumber(obj, &n)) /* cannot convert to float? */
      return 0;  /* not a number */
    if (luai_numlt(0, n)) {  /* if true, float is larger than max integer */
      *p = LUA_MAXINTEGER;
      if (step < 0) *stopnow = 1;
    }
    else {  /* float is smaller than min integer */
      *p = LUA_MININTEGER;
      if (step >= 0) *stopnow = 1;
    }
  }
  return 1;
}