pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:13:
#include "stralloc.h" #include "opcodes.h" #include "operators.h" #include "language.h" #include "memory.h" #include "error.h" #include "docode.h" #include "add_efun.h" #include "peep.h" #include "lex.h"
+
#include "program.h"
+
#include "object.h"
#define COMPARISON(ID,NAME,EXPR) \ void ID(INT32 args) \ { \ int i; \ if(args > 2) \ pop_n_elems(args-2); \ else if(args < 2) \ error("Too few arguments to %s\n",NAME); \ i=EXPR; \ pop_n_elems(2); \
-
sp->type=T
_
INT; \
-
sp->u.integer=
i; \
-
sp++; \
+
push
_
int(
i
)
; \
} COMPARISON(f_eq,"`==", is_eq(sp-2,sp-1)) COMPARISON(f_ne,"`!=",!is_eq(sp-2,sp-1)) COMPARISON(f_lt,"`<" , is_lt(sp-2,sp-1)) COMPARISON(f_le,"`<=",!is_gt(sp-2,sp-1)) COMPARISON(f_gt,"`>" , is_gt(sp-2,sp-1)) COMPARISON(f_ge,"`>=",!is_lt(sp-2,sp-1))
-
+
#define CALL_OPERATOR(OP, args) \
+
if(!sp[-args].u.object->prog) \
+
error("Operator %s called in destructed object.\n",lfun_names[OP]); \
+
if(sp[-args].u.object->prog->lfuns[OP] == -1) \
+
error("No operator %s in object.\n",lfun_names[OP]); \
+
apply_lfun(sp[-args].u.object, OP, args-1); \
+
free_svalue(sp-2); \
+
sp[-2]=sp[-1]; \
+
sp--;
+
+
void f_add(INT32 args) { INT32 e,size; TYPE_FIELD types; types=0; for(e=-args;e<0;e++) types|=1<<sp[e].type; switch(types) { default: if(args) { switch(sp[-args].type) { case T_OBJECT:
-
+
CALL_OPERATOR(LFUN_ADD,args);
+
return;
+
case T_PROGRAM: case T_FUNCTION: error("Bad argument 1 to summation\n"); } } error("Incompatible types to sum() or +\n"); return; /* compiler hint */ case BIT_STRING: {
pike.git/src/operators.c:331:
{ sp[-1].u.float_number=(FLOAT_TYPE)sp[-1].u.integer; sp[-1].type=T_FLOAT; } return sp[-2].type == sp[-1].type; } void o_subtract() {
-
if (sp[-2].type != sp[-1].type && !float_promote())
+
if (sp[-2].type != sp[-1].type &&
+
!float_promote()
&&
+
sp[-2].type != T_OBJECT
)
error("Subtract on different types.\n");
-
switch(sp[-
1
].type)
+
switch(sp[-
2
].type)
{
-
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_SUBTRACT,2);
+
break;
+
case T_ARRAY: { struct array *a; check_array_for_destruct(sp[-2].u.array); check_array_for_destruct(sp[-1].u.array); a = subtract_arrays(sp[-2].u.array, sp[-1].u.array); pop_n_elems(2); push_array(a); return;
pike.git/src/operators.c:424:
case 2: do_docode(CDR(n),DO_NOT_COPY); emit2(F_SUBTRACT); return 1; } return 0; } void o_and() {
-
if(sp[-1].type != sp[-2].type)
+
if(sp[-1].type != sp[-2].type
&&
+
sp[-2].type != T_OBJECT
)
error("Bitwise and on different types.\n"); switch(sp[-2].type) {
-
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_AND,2);
+
break;
+
case T_INT: sp--; sp[-1].u.integer &= sp[0].u.integer; break; case T_MAPPING: { struct mapping *m; m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_AND); pop_n_elems(2);
pike.git/src/operators.c:472:
} } void f_and(INT32 args) { switch(args) { case 0: error("Too few arguments to `&\n"); case 1: return; case 2: o_and(); return;
-
default: while(--args > 0) o_and();
+
default:
+
if(sp[-args].type == T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_AND, args);
+
}else{
+
while(--args > 0) o_and();
} }
-
+
}
static int generate_and(node *n) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2:
pike.git/src/operators.c:496:
emit2(F_AND); return 1; default: return 0; } } void o_or() {
-
if(sp[-1].type != sp[-2].type)
+
if(sp[-1].type != sp[-2].type
&&
+
sp[-2].type != T_OBJECT
)
error("Bitwise or on different types.\n"); switch(sp[-2].type) {
-
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_OR,2);
+
break;
+
case T_INT: sp--; sp[-1].u.integer |= sp[0].u.integer; break; case T_MAPPING: { struct mapping *m; m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_OR); pop_n_elems(2);
pike.git/src/operators.c:545:
} } void f_or(INT32 args) { switch(args) { case 0: error("Too few arguments to `|\n"); case 1: return; case 2: o_or(); return;
-
default: while(--args > 0) o_or();
+
default:
+
if(sp[-args].type==T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_OR, args);
+
} else {
+
while(--args > 0) o_or();
} }
-
+
}
static int generate_or(node *n) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2:
pike.git/src/operators.c:570:
return 1; default: return 0; } } void o_xor() {
-
if(sp[-1].type != sp[-2].type)
+
if(sp[-1].type != sp[-2].type
&&
+
sp[-2].type != T_OBJECT
)
error("Bitwise xor on different types.\n"); switch(sp[-2].type) {
-
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_XOR,2);
+
break;
+
case T_INT: sp--; sp[-1].u.integer ^= sp[0].u.integer; break; case T_MAPPING: { struct mapping *m; m=merge_mappings(sp[-2].u.mapping, sp[-1].u.mapping, OP_XOR); pop_n_elems(2);
pike.git/src/operators.c:618:
} } void f_xor(INT32 args) { switch(args) { case 0: error("Too few arguments to `^\n"); case 1: return; case 2: o_xor(); return;
-
default: while(--args > 0) o_xor();
+
default:
+
if(sp[-args].type==T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_XOR, args);
+
} else {
+
while(--args > 0) o_xor();
} }
-
+
}
static int generate_xor(node *n) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2:
pike.git/src/operators.c:642:
emit2(F_XOR); return 1; default: return 0; } } void o_lsh() {
-
if(sp[-2].type != T_INT) error("Bad argument 1 to <<\n");
+
if(sp[-2].type != T_INT)
+
{
+
if(sp[-2].type == T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_LSH,2);
+
return;
+
}
+
+
error("Bad argument 1 to <<\n");
+
}
if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n"); sp--; sp[-1].u.integer = sp[-1].u.integer << sp->u.integer; } void f_lsh(INT32 args) { if(args != 2) error("Bad number of args to `<<\n"); o_lsh();
pike.git/src/operators.c:668:
{ do_docode(CDR(n),DO_NOT_COPY); emit2(F_LSH); return 1; } return 0; } void o_rsh() {
-
if(sp[-2].type != T_INT) error("Bad argument 1 to >>\n");
+
if(sp[-2].type != T_INT)
+
{
+
if(sp[-2].type == T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_RSH,2);
+
return;
+
}
+
error("Bad argument 1 to >>\n");
+
}
if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n"); sp--; sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer; } void f_rsh(INT32 args) { if(args != 2) error("Bad number of args to `>>\n"); o_rsh();
pike.git/src/operators.c:733:
(FLOAT_TYPE) sp[-1].u.integer * (FLOAT_TYPE)sp[0].u.float_number; sp[-1].type=T_FLOAT; return; case TWO_TYPES(T_INT,T_INT): sp--; sp[-1].u.integer *= sp[0].u.integer; return; default:
+
if(sp[-2].type == T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_MULTIPLY,2);
+
return;
+
}
+
error("Bad arguments to multiply.\n"); } } void f_multiply(INT32 args) { switch(args) { case 0: error("Too few arguments to `*\n"); case 1: return; case 2: o_multiply(); return;
-
default: while(--args > 0) o_multiply();
+
default:
+
if(sp[-args].type==T_OBJECT)
+
{
+
CALL_OPERATOR(LFUN_MULTIPLY, args);
+
} else {
+
while(--args > 0) o_multiply();
} }
-
+
}
static int generate_multiply(node *n) { switch(count_args(CDR(n))) { case 1: do_docode(CDR(n),0); return 1; case 2:
pike.git/src/operators.c:768:
emit2(F_MULTIPLY); return 1; default: return 0; } } void o_divide() {
-
if(sp[-2].type!=sp[-1].type && !float_promote())
+
if(sp[-2].type!=sp[-1].type &&
+
!float_promote()
&&
+
sp[-2].type != T_OBJECT
)
error("Division on different types.\n"); switch(sp[-2].type) {
-
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_DIVIDE,2);
+
break;
+
case T_STRING: { struct array *ret; ret=explode(sp[-2].u.string,sp[-1].u.string); free_string(sp[-2].u.string); free_string(sp[-1].u.string); sp[-2].type=T_ARRAY; sp[-2].u.array=ret; sp--; return;
pike.git/src/operators.c:824:
{ do_docode(CDR(n),DO_NOT_COPY); emit2(F_DIVIDE); return 1; } return 0; } void o_mod() {
-
if(sp[-2].type != sp[-1].type && !float_promote())
+
if(sp[-2].type != sp[-1].type &&
+
!float_promote()
&&
+
sp[-2].type != T_OBJECT
)
error("Modulo on different types.\n");
-
switch(sp[-
1
].type)
+
switch(sp[-
2
].type)
{
-
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_MOD,2);
+
break;
+
case T_FLOAT: { FLOAT_TYPE foo; if(sp[-1].u.float_number == 0.0) error("Modulo by zero.\n"); sp--; foo=sp[-1].u.float_number / sp[0].u.float_number; foo=sp[-1].u.float_number - sp[0].u.float_number * floor(foo); sp[-1].u.float_number=foo; return;
pike.git/src/operators.c:871:
{ do_docode(CDR(n),DO_NOT_COPY); emit2(F_MOD); return 1; } return 0; } void o_not() {
-
if
(sp[-1].type
==T_INT
)
+
switch
(sp[-1].type)
{
-
+
case T_INT:
sp[-1].u.integer = !sp[-1].u.integer;
-
+
break;
+
+
case T_FUNCTION:
+
case T_OBJECT:
+
if(IS_ZERO(sp-1))
+
{
+
pop_stack();
+
push_int(1);
}else{ pop_stack();
-
sp->type=T_INT;
-
sp->u.integer=
0;
-
sp++;
+
push_int(
0
)
;
}
-
+
break;
+
+
default:
+
free_svalue(sp-1);
+
sp[-1].type=T_INT;
+
sp[-1].u.integer=0;
}
-
+
}
void f_not(INT32 args) { if(args != 1) error("Bad number of args to `!\n"); o_not(); } static int generate_not(node *n) { if(count_args(CDR(n))==1)
pike.git/src/operators.c:903:
emit2(F_NOT); return 1; } return 0; } void o_compl() { switch(sp[-1].type) {
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_COMPL,1);
+
break;
+
case T_INT: sp[-1].u.integer = ~ sp[-1].u.integer; break; case T_FLOAT: sp[-1].u.float_number = -1.0 - sp[-1].u.float_number; break; default: error("Bad argument to ~\n");
pike.git/src/operators.c:937:
emit2(F_COMPL); return 1; } return 0; } void o_negate() { switch(sp[-1].type) {
+
case T_OBJECT:
+
CALL_OPERATOR(LFUN_SUBTRACT,1);
+
break;
+
case T_FLOAT: sp[-1].u.float_number=-sp[-1].u.float_number; return; case T_INT: sp[-1].u.integer = - sp[-1].u.integer; return; default: error("Bad argument to unary minus\n");
pike.git/src/operators.c:1009:
default: error("[ .. ] can only be done on strings and arrays.\n"); } } void init_operators() { add_efun2("`==",f_eq,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); add_efun2("`!=",f_ne,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
-
add_efun2("`
<
",
f_
lt
,"function(
int|float,int|float
:int)
|function(string,string:int)
",OPT_TRY_OPTIMIZE,0,generate_
comparison
);
-
add_efun2("`<=",f_le,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
-
add_efun2("`>", f_gt,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
-
add_efun2("`>=",f_ge,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
+
add_efun2("`
!
",f_
not
,"function(
mixed
:int)",OPT_TRY_OPTIMIZE,0,generate_
not
);
-
add
_
efun2(
"
`+",f_add,"
function(
int...
:int)|
!
function(
int...:
mixed
)&function(int|float...
:
float
)|
!
function(int|float
...:mixed)&function(string|
int|float
...
:
string
)|function(
array...
:
array
)
|function
(
mapping...:mapping
)
|function
(
list...:list
)",OPT_TRY_OPTIMIZE,
optimize
_
binary
,generate_
sum
);
+
#define
CMP_TYPE
"function(
object,mixed
:int)|function(
mixed,object
:int)|function(int|float
,
int|float:
int
)|function(
string,string
:
int
)
"
+
add_efun2
(
"`<", f_lt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison
)
;
+
add_efun2
(
"`<=",f_le,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison
)
;
+
add_efun2(
"
`>"
,
f_gt,CMP_TYPE,
OPT_TRY_OPTIMIZE,
0,generate
_
comparison);
+
add_efun2("`>="
,
f_ge,CMP_TYPE,OPT_TRY_OPTIMIZE,0,
generate_
comparison
);
-
add_efun2("
`-
",f_
minus
,"function(
int
:
int
)|function(
float
:
float
)|function(
array,array
:
array
)
|
function(
mapping,mapping
:
mapping
)|function(
list,list
:
list
)
|
function(
float
|int
,
float:
float
)|function(
float,int
:
float
)|function(
int,int
:
int
)|function(
string,string
:
string
)",OPT_TRY_OPTIMIZE,
0
,generate_
minus
);
+
add_efun2("
`+
",f_
add
,"function(
object,mixed...
:
mixed
)|function(
int...
:
int
)|
!
function(
int...
:
mixed
)
&
function(
int|float...
:
float
)|
!
function(
int|float...
:
mixed
)
&
function(
string
|int
|
float
...
:
string
)|function(
array...
:
array
)|function(
mapping...
:
mapping
)|function(
list...
:
list
)",OPT_TRY_OPTIMIZE,
optimize_binary
,generate_
sum
);
-
add_efun2("`
&
",f_
and
,"function(
int
...:int)|function(mapping
...
:mapping)|function(list
...
:list)|function(
array...
:
array
)",OPT_TRY_OPTIMIZE,
optimize_binary
,generate_
and
);
+
add_efun2("`
-
",f_
minus
,"function(
object,mixed
...:
mixed)|function(
int
:int
)|function(
float:float)|function(array,array:array)|function(
mapping
,mapping
:mapping)|function(list
,list
:list)|function(
float|int,float
:
float
)
|function(float,int:float)|function(int,int:int)|function(string,string:string)
",OPT_TRY_OPTIMIZE,
0
,generate_
minus
);
-
add
_
efun2(
"
`|"
,
f_or,"
function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)"
,OPT_TRY_OPTIMIZE,optimize_binary,generate_or);
+
#define
LOG_TYPE
"function
(
object,mixed...:mixed)
|function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)"
-
add_efun2("`
^
",f_
xor
,
"function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)"
,OPT_TRY_OPTIMIZE,optimize_binary,generate_
xor
);
+
add_efun2("`
&
",f_
and
,
LOG_TYPE
,OPT_TRY_OPTIMIZE,optimize_binary,generate_
and
);
-
add_efun2("`
<<
",f_
lsh
,
"function(int
,
int:int)",
OPT_TRY_OPTIMIZE,
0,generate
_
lsh);
-
add_efun2("`>>"
,
f_rsh,"function(int,int:int)",OPT_TRY_OPTIMIZE,0,
generate_
rsh
);
+
add_efun2("`
|
",f_
or
,
LOG_TYPE
,OPT_TRY_OPTIMIZE,
optimize
_
binary
,generate_
or
);
-
add_efun2("`
*
",f_
multiply
,
"function(int...:int)|!function(int...:mixed)&function(float|int...:float)|function(string*
,
string:string)",
OPT_TRY_OPTIMIZE,optimize_binary,generate_
multiply
);
+
add_efun2("`
^
",f_
xor
,
LOG_TYPE
,OPT_TRY_OPTIMIZE,optimize_binary,generate_
xor
);
-
add_efun2("`/",f_divide,"function(int,int:int)|function(float|int,float:float)|function(float,int:float)|function(string,string:string*)",OPT_TRY_OPTIMIZE,0,generate_divide);
+
-
add
_
efun2(
"
`%",f_mod,"
function(
int
,
int
:
int
)|
!
function(int,int:
mixed)&function(
int
|float,int|float:float
)"
,OPT_TRY_OPTIMIZE,0,generate_mod);
+
#define
SHIFT_TYPE
"function(
object
,
mixed
:
mixed
)|function(int,int:int)"
-
add_efun2("`!",f_
not
,"function(mixed:int)",OPT_TRY_OPTIMIZE,0,generate_
not
);
-
add_efun2("`~",f_compl,"function(int:int)|function(float:float)",OPT_TRY_OPTIMIZE,0,generate_compl);
+
add_efun2("`
<<",f_lsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_lsh);
+
add_efun2("`>>",f_rsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_rsh);
+
+
add_efun2("`*",f_multiply,"function(object,mixed...:mixed)|function(int...:int)|
!
function(int...:mixed)&function(float|int...:float)|function(string*,string:string)
",
OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply);
+
+
add_efun2("`/",
f_
divide
,"function(
object,
mixed:
mixed)|function(
int
,int:int
)
|function(float|int,float:float)|function(float,int:float)|function(string,string:string*)
",OPT_TRY_OPTIMIZE,0,generate_
divide
);
+
+
add_efun2("`
%",f_mod,"function(object,mixed:mixed)|function(int,int:int)|!function(int,int:mixed)&function(int|float,int|float:float)",OPT_TRY_OPTIMIZE,0,generate_mod);
+
+
add_efun2("`
~",f_compl,"function(
object:mixed)|function(
int:int)|function(float:float)",OPT_TRY_OPTIMIZE,0,generate_compl);
}