pike.git / src / operators.c

version» Context lines:

pike.git/src/operators.c:3377:    modify_stack_depth(-1);    return 1;       default:    return 0;    }   }      PMOD_EXPORT void o_lsh(void)   { -  if (sp[-1].u.integer < 0) { +     int args = 2; -  +  if ((TYPEOF(sp[-2]) == T_OBJECT) || +  (TYPEOF(sp[-1]) == T_OBJECT)) +  goto call_lfun; +  +  if ((TYPEOF(sp[-1]) != T_INT) || (sp[-1].u.integer < 0)) {    SIMPLE_BAD_ARG_ERROR("`<<", 2, "int(0..)|object");    } -  if ((TYPEOF(sp[-1]) == T_INT) && (TYPEOF(sp[-2]) == T_INT) && -  INT_TYPE_LSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer)) +  +  switch(TYPEOF(sp[-2])) { +  case T_INT: +  if (!INT_TYPE_LSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer)) +  break;    convert_stack_top_to_bignum();    -  if(TYPEOF(sp[-1]) != T_INT || TYPEOF(sp[-2]) != T_INT) -  { -  int args = 2; +  /* FALL_THROUGH */ +  +  case T_OBJECT: +  call_lfun:    if(call_lfun(LFUN_LSH, LFUN_RLSH))    return;       if(TYPEOF(sp[-2]) != T_INT) -  SIMPLE_BAD_ARG_ERROR("`<<", 1, "int|object"); +  SIMPLE_BAD_ARG_ERROR("`<<", 1, "int|float|object");    SIMPLE_BAD_ARG_ERROR("`<<", 2, "int(0..)|object"); -  +  break; +  +  case T_FLOAT: +  sp--; +  sp[-1].u.float_number = ldexp(sp[-1].u.float_number, sp->u.integer); +  return; +  +  default: +  SIMPLE_BAD_ARG_ERROR("`<<", 1, "int|float|object"); +  break;    }       sp--;    SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer,    sp[-1].u.integer << sp->u.integer);   }    - /*! @decl int `<<(int arg1, int arg2) -  *! @decl mixed `<<(object arg1, int|object arg2) + /*! @decl int `<<(int arg1, int(0..) arg2) +  *! @decl mixed `<<(object arg1, int(0..)|object arg2)    *! @decl mixed `<<(int arg1, object arg2) -  +  *! @decl mixed `<<(float arg1, int(0..) arg2)    *!    *! Left shift.    *!    *! Every expression with the @expr{<<@} operator becomes a call to    *! this function, i.e. @expr{a<<b@} is the same as    *! @expr{predef::`<<(a,b)@}.    *!    *! If @[arg1] is an object that implements @[lfun::`<<()], that    *! function will be called with @[arg2] as the single argument.    *!    *! If @[arg2] is an object that implements @[lfun::``<<()], that    *! function will be called with @[arg1] as the single argument.    *! -  +  *! If @[arg1] is a float and @[arg2] is a non-negative integer, +  *! @[arg1] will be multiplied by @expr{1<<@[arg2]@}. +  *!    *! Otherwise @[arg1] will be shifted @[arg2] bits left.    *!    *! @seealso    *! @[`>>()]    */   PMOD_EXPORT void f_lsh(INT32 args)   {    if(args != 2) {    /* FIXME: Not appropriate if too many args. */    SIMPLE_TOO_FEW_ARGS_ERROR("`<<", 2);
pike.git/src/operators.c:3446:    do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL);    emit0(F_LSH);    modify_stack_depth(-1);    return 1;    }    return 0;   }      PMOD_EXPORT void o_rsh(void)   { -  if(TYPEOF(sp[-2]) != T_INT || TYPEOF(sp[-1]) != T_INT) -  { +     int args = 2; -  +  if ((TYPEOF(sp[-2]) == T_OBJECT) || (TYPEOF(sp[-1]) == T_OBJECT)) +  {    if(call_lfun(LFUN_RSH, LFUN_RRSH))    return;    if(TYPEOF(sp[-2]) != T_INT)    SIMPLE_BAD_ARG_ERROR("`>>", 1, "int|object");    SIMPLE_BAD_ARG_ERROR("`>>", 2, "int(0..)|object");    }    -  if (sp[-1].u.integer < 0) { -  int args = 2; +  if ((TYPEOF(sp[-1]) != T_INT) || (sp[-1].u.integer < 0)) {    SIMPLE_BAD_ARG_ERROR("`>>", 2, "int(0..)|object");    }    -  if( INT_TYPE_RSH_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer) ) -  { +     sp--; -  +  switch(TYPEOF(sp[-1])) { +  case T_INT: +  if( INT_TYPE_RSH_OVERFLOW(sp[-1].u.integer, sp->u.integer) ) +  {    if (sp[-1].u.integer < 0) {    SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, -1);    } else {    SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer, 0);    }    return;    } -  +  break; +  case T_FLOAT: +  sp[-1].u.float_number = ldexp(sp[-1].u.float_number, -sp->u.integer); +  return; +  default: +  SIMPLE_BAD_ARG_ERROR("`>>", 1, "int|float|object"); +  break; +  }    -  sp--; +     SET_SVAL(sp[-1], T_INT, NUMBER_NUMBER, integer,    sp[-1].u.integer >> sp->u.integer);   }    - /*! @decl int `>>(int arg1, int arg2) -  *! @decl mixed `>>(object arg1, int|object arg2) + /*! @decl int `>>(int arg1, int(0..) arg2) +  *! @decl mixed `>>(object arg1, int(0..)|object arg2)    *! @decl mixed `>>(int arg1, object arg2) -  +  *! @decl float `>>(float arg1, int(0..) arg2)    *!    *! Right shift.    *!    *! Every expression with the @expr{>>@} operator becomes a call to    *! this function, i.e. @expr{a>>b@} is the same as    *! @expr{predef::`>>(a,b)@}.    *!    *! If @[arg1] is an object that implements @[lfun::`>>()], that    *! function will be called with @[arg2] as the single argument.    *!    *! If @[arg2] is an object that implements @[lfun::``>>()], that    *! function will be called with @[arg1] as the single argument.    *! -  +  *! If @[arg1] is a float and @[arg2] is a non-negative integer, +  *! @[arg1] will be divided by @expr{1<<@[arg2]@}. +  *!    *! Otherwise @[arg1] will be shifted @[arg2] bits right.    *!    *! @seealso    *! @[`<<()]    */   PMOD_EXPORT void f_rsh(INT32 args)   {    if(args != 2) {    /* FIXME: Not appropriate if too many args. */    SIMPLE_TOO_FEW_ARGS_ERROR("`>>", 2);
pike.git/src/operators.c:5817:    tFuncV(tSetvar(3,tMultiset),tSetvar(4,tMultiset),tOr(tVar(3),tVar(4))), \    tFuncV(tSetvar(5,tArray),tSetvar(6,tArray),tOr(tVar(5),tVar(6))), \    tFuncV(tString,tString,tString), \    tFuncV(tOr(tType(tMix),tPrg(tObj)),tOr(tType(tMix),tPrg(tObj)),tType(tMix)))       ADD_EFUN2("`|",f_or,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_or);       ADD_EFUN2("`^",f_xor,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_xor);      #define SHIFT_TYPE \ -  tOr3(tIfnot(tFuncV(tNone, tNot(tObj), tMix), \ +  tOr4(tIfnot(tFuncV(tNone, tNot(tObj), tMix), \    tOr(tFunc(tMix tObj,tMix), \    tFunc(tObj tMix,tMix))), \    tIfnot(tFuncV(tNone, tNot(tInt), tMix), \    tFunc(tInt tInt, tInt)), \ -  +  tFunc(tFloat tIntPos, tFloat), \    tFunc(tIntPos tIntPos, tIntPos))       ADD_EFUN2("`<<", f_lsh, SHIFT_TYPE, OPT_TRY_OPTIMIZE,    may_have_side_effects, generate_lsh);    ADD_EFUN2("`>>", f_rsh, SHIFT_TYPE, OPT_TRY_OPTIMIZE,    may_have_side_effects, generate_rsh);       /* !function(!object...:mixed)&function(mixed...:mixed)|"    "function(array(array(1=mixed)),array(1=mixed):array(1))|"    "function(int...:int)|"