pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:1:
/* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
-
|| $Id: operators.c,v 1.
181
2003/11/
10
01
:
42
:
32
mast Exp $
+
|| $Id: operators.c,v 1.
182
2003/11/
12
18
:
59
:
17
mast Exp $
*/ #include "global.h" #include <math.h>
-
RCSID("$Id: operators.c,v 1.
181
2003/11/
10
01
:
42
:
32
mast Exp $");
+
RCSID("$Id: operators.c,v 1.
182
2003/11/
12
18
:
59
:
17
mast Exp $");
#include "interpret.h" #include "svalue.h" #include "multiset.h" #include "mapping.h" #include "array.h" #include "stralloc.h" #include "opcodes.h" #include "operators.h" #include "language.h" #include "pike_memory.h"
pike.git/src/operators.c:224:
if((i = FIND_LFUN(sp[-args].u.object->prog,OP)) == -1) \ bad_arg_error(lfun_names[OP], sp-args, args, 1, "object", sp-args, \ "Operator not in object.\n"); \ apply_low(sp[-args].u.object, i, args-1); \ free_svalue(sp-2); \ sp[-2]=sp[-1]; \ sp--; \ dmalloc_touch_svalue(sp); \ } while (0)
-
/*! @decl mixed `+(mixed
arg1
)
-
*! @decl mixed `+(object
arg1
, mixed ...
extras
)
-
*! @decl
mixed
`+(
mixed
arg1
,
mixed
arg2, mixed
...
extras
)
-
*! @decl
int `+(int arg1, int arg2)
-
*! @decl
float `+(float
arg1, int
|
float arg2)
-
*! @decl float `+(
int
|float
arg1
, float
arg2)
-
*! @decl string `+(int
|
float
arg1,
string arg2
)
-
*! @decl string `+(string
arg1
, string|
int|
float
arg2
)
-
*! @decl array `+(array
arg1
, array
arg2
)
-
*! @decl mapping `+(mapping
arg1
, mapping
arg2
)
-
*! @decl multiset `+(multiset
arg1
, multiset
arg2
)
+
/*! @decl mixed `+(mixed
arg
)
+
*! @decl mixed `+(object
arg
, mixed ...
more
)
+
*! @decl
int
`+(
int
arg
,
int
...
more
)
+
*! @decl float `+(float|int
arg
, float
|
int
...
more
)
+
*! @decl string `+(string
|float|int
arg
, string|
float|
int
... more
)
+
*! @decl array `+(array
arg
, array
... more
)
+
*! @decl mapping `+(mapping
arg
, mapping
... more
)
+
*! @decl multiset `+(multiset
arg
, multiset
... more
)
*! *! Addition/concatenation. *! *! 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)@}. Longer @expr{+@} expressions are *! normally optimized to one call, so e.g. @expr{a+b+c@} becomes *! @expr{predef::`+(a,b,c)@}. *! *! @returns *! If there's a single argument, that argument is returned. *!
-
*! If @[
arg1
] is an object with only one reference and an
+
*! If @[
arg
] is an object with only one reference and an
*! @[lfun::`+=()], that function is called with the rest of the *! arguments, and its result is returned. *!
-
*! Otherwise, if @[
arg1
] is an object with an @[lfun::`+()], that
+
*! Otherwise, if @[
arg
] is an object with an @[lfun::`+()], that
*! function is called with the rest of the arguments, and its *! result is returned. *! *! Otherwise, if any of the other arguments is an object that has *! an @[lfun::``+()], the first such function is called with the *! arguments leading up to it, and @[`+()] is then called *! recursively with the result and the rest of the arguments. *!
-
*! Otherwise, if
there
are
more
than
two
arguments the
result
is
:
-
*!
@expr{`+(`+(@[arg1],
@
[
arg2
])
,
@@@
[
extras
]
)
@}
+
*! Otherwise, if
@[arg]
is
@[UNDEFINED]
and
the
other
arguments
are
+
*! either arrays, mappings or multisets,
the
first
argument
is
+
*!
ignored and the remaining are added together as described below.
+
*! This is useful primarily when appending to mapping values since
+
*! @expr{m
[
x
]
+= ({foo}
)
@}
will work even if @expr{m
[
x
]@}
doesn't
+
*! exist yet.
*! *! Otherwise the result depends on the argument types:
-
*! @mixed
arg1
+
*! @mixed
*! @type int|float
-
*!
@mixed arg2
-
*! @type int|float
-
*!
The result is
@expr{@[arg1]
+
@[arg2]@},
and
is
a float
-
*!
if either @[arg1] or @[arg2]
is a float.
-
*!
@type string
-
*!
@[arg1]
is
converted
to
string
which
is
concatenated
-
*!
with @[arg2].
-
*!
@endmixed
-
*!
@type string
-
*! @[arg2] is converted
to
a
string, and
the result
is
-
*! concatenated to the end of @[arg1]
.
+
*! The result is
the
sum
of
all
the
arguments. It's
a float
if
+
*!
any
argument
is a float.
+
*! @type string
|int|float
+
*!
If
any
argument
is
a
string
,
all
will
be
converted
to
+
*!
strings
and
concatenated
in
order
to
form
the result.
*! @type array
-
*! The
result
is
@[arg2]
concatenated
to the
end
of
@[arg1]
.
+
*! The
array
arguments
are
concatened
in order
to
form
the
+
*!
result
.
*! @type mapping
-
*! The result is like @[
arg1
] but extended with the entries
-
*!
from
@[arg2]
. If the same index (according to
@[hash_value]
-
*! and @[`==]) occur in
both
, the value from
@[arg2]
is used.
+
*! The result is like @[
arg
] but extended with the entries
from
+
*!
the
other arguments
. If the same index (according to
+
*!
@[hash_value]
and @[`==]) occur in
several arguments
, the
+
*!
value from
the
last one
is used.
*! @type multiset
-
*! The result is like @[
arg1
] but extended with the entries
-
*!
from
@[arg2]
. Subsequences with orderwise equal
indices
-
*! (i.e. where @[`<] returns false) are concatenated
into the
-
*!
result
with
the
subsequence
from
@[arg1]
before the one from
-
*! @[arg2]
.
+
*! The result is like @[
arg
] but extended with the entries
from
+
*!
the
other arguments
. Subsequences with orderwise equal
+
*!
indices
(i.e. where @[`<] returns false) are concatenated
+
*!
into
the
result
in
argument
order
.
*! @endmixed *! The function is not destructive on the arguments - the result is *! always a new instance. *! *! @note *! In Pike 7.0 and earlier the addition order was unspecified. *!
-
*!
If
@[
arg1
]
is @expr{UNDEFINED@} it will behave as the empty
-
*! array/mapping/multiset if needed. This behaviour
was new
+
*!
The
treatment of
@[
UNDEFINED
] was new
*! in Pike 7.0. *! *! @seealso *! @[`-()], @[lfun::`+()], @[lfun::``+()] */ PMOD_EXPORT void f_add(INT32 args) { INT_TYPE e,size; TYPE_FIELD types;
pike.git/src/operators.c:593:
}else{ sum+=(FLOAT_TYPE)sp[e].u.integer; } } sp-=args-1; sp[-1].type=T_FLOAT; sp[-1].u.float_number=sum; break; }
-
case
BIT
_
ARRAY|BIT
_
INT:
-
{
-
if(IS_UNDEFINED(sp-args))
-
{
-
int e;
-
struct
array
*a
;
+
#define
ADD_WITH_UNDEFINED(TYPE,
T_TYPEID,
ADD
_
FUNC, PUSH
_
FUNC) do { \
+
int e; \
+
if (sp[-args].type == T_INT)
{
\
+
if(IS_UNDEFINED(sp-args))
\
+
{
\
+
struct TYPE *x; \
+
\
+
for(e=1;e<args;e++) \
+
if(sp[e-args].type != T_TYPEID) \
+
SIMPLE_ARG_TYPE_ERROR("`+", e+1, #TYPE); \
+
\
+
x = ADD_FUNC(sp-args+1,args-1); \
+
pop_n_elems(args); \
+
PUSH_FUNC(x); \
+
return; \
+
} \
+
\
+
for(e=1;e<args;e++) \
+
if (sp[e-args].type != T_INT) \
+
SIMPLE_ARG_TYPE_ERROR("`+", e+1, "
int
");
\
+
} \
+
\
+
else { \
+
for(
e
=1
;
e<args;e++) \
+
if (sp[e-args].type != T_TYPEID) \
+
SIMPLE_ARG_TYPE_ERROR("`+", e+1, #TYPE)
;
\
+
} \
+
\
+
DO_IF_DEBUG (Pike_fatal ("Shouldn't be reached.\n")); \
+
} while (0)
-
for(e=1;e<args;e++)
-
if
(sp
[e
-args
].type
!= T_ARRAY
)
-
SIMPLE
_
BAD
_
ARG_ERROR
(
"`+",
e+1,
"array"
);
+
#define
ADD(TYPE,
ADD_FUNC,
PUSH_FUNC)
do
{
\
+
struct
TYPE
*x
=
ADD_FUNC
(sp
-
args
,
args);
\
+
pop
_
n_elems (args
)
;
\
+
PUSH
_
FUNC
(
x);
\
+
return; \
+
} while (0
)
-
a=add
_
arrays(sp-args+1,args-1);
-
pop
_
n_elems(args);
-
push
_
array(a);
-
return;
-
}
-
if (sp[-args].type == T
_
INT)
{
-
int e;
-
for
(
e=1;e<args;e++)
-
if (sp[e-args].type != T_INT)
-
SIMPLE_BAD_ARG_ERROR("`+"
,
e+1, "int");
-
} else {
-
int e;
-
for(e=0;e<args;e++)
-
if (sp[e-args].type !=
T_ARRAY
)
-
SIMPLE_BAD_ARG_ERROR("`+"
,
e+1, "array");
-
}
-
/* Probably not reached, but... */
-
bad
_
arg_error("`+"
,
sp-args, args, 1, "
array
", sp-args,
-
"trying to add integers and arrays.\n"
);
-
}
+
case
BIT
_
ARRAY|BIT
_
INT:
+
ADD
_
WITH
_
UNDEFINED
(
array
, T_ARRAY
,
add
_
arrays
,
push
_array);
case BIT_ARRAY:
-
{
-
struct
array
*a;
-
a=
add_arrays
(sp-args
,
args);
-
pop_n_elems(args);
-
push_array
(a
);
-
break;
-
}
+
ADD
(
array
,
add_arrays, push_array);
case BIT_MAPPING|BIT_INT:
-
{
-
if(IS
_UNDEFINED(
sp-args))
-
{
-
int e;
-
struct
mapping
*a
;
+
ADD
_
WITH_
UNDEFINED
(
mapping,
T_MAPPING,
add_mappings,
push_
mapping
)
;
-
for(e=1;e<args;e++)
-
if(sp[e-args].type != T_MAPPING)
-
SIMPLE_BAD_ARG_ERROR("`+", e+1, "mapping");
-
-
a=add_mappings(sp-args+1,args-1);
-
pop_n_elems(args);
-
push_mapping(a);
-
return;
-
}
-
if (sp[-args].type == T_INT) {
-
int e;
-
for(e=1;e<args;e++)
-
if (sp[e-args].type != T_INT)
-
SIMPLE_BAD_ARG_ERROR("`+", e+1, "int");
-
} else {
-
int e;
-
for(e=0;e<args;e++)
-
if (sp[e-args].type != T_MAPPING)
-
SIMPLE_BAD_ARG_ERROR("`+", e+1, "mapping");
-
}
-
/* Probably not reached, but... */
-
bad_arg_error("`+", sp-args, args, 1, "mapping", sp-args,
-
"Trying to add integers and mappings.\n");
-
}
-
+
case BIT_MAPPING:
-
{
-
struct
mapping
*m
;
+
ADD
(mapping,
add_mappings,
push_
mapping
)
;
-
m = add
_
mappings(sp - args, args);
-
pop
_
n
_
elems
(
args);
-
push_
mapping(m
);
-
break;
-
}
+
case
BIT
_
MULTISET|BIT_INT:
+
ADD
_
WITH
_
UNDEFINED
(
multiset,
T_MULTISET,
add_multisets,
push_
multiset
);
case BIT_MULTISET:
-
{
-
struct
multiset
*l
;
+
ADD
(multiset,
add_multisets,
push_
multiset
)
;
-
l = add
_
multisets(sp - args, args);
-
pop
_
n_elems(args);
-
push_multiset(l);
-
break;
+
#undef
ADD
_
WITH
_
UNDEFINED
+
#undef
ADD
} }
-
}
+
static int generate_sum(node *n) { node **first_arg, **second_arg; switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1;