From 1b89ad58b37799d1fcce495f7be9bf466aebc3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Fri, 10 Oct 1997 23:49:20 -0700 Subject: [PATCH] right-side operator overloading implemented Rev: src/array.c:1.18 Rev: src/interpret.c:1.49 Rev: src/lex.c:1.28 Rev: src/modules/Gmp/mpz_glue.c:1.23 Rev: src/modules/Gmp/testsuite.in:1.7 Rev: src/operators.c:1.20 Rev: src/program.c:1.43 Rev: src/program.h:1.21 --- src/array.c | 4 +- src/interpret.c | 25 +---- src/lex.c | 62 ++++++------ src/modules/Gmp/mpz_glue.c | 109 +++++++++++++++++++-- src/modules/Gmp/testsuite.in | 67 ++++++++----- src/operators.c | 179 +++++++++++++++++++++++++---------- src/program.c | 12 ++- src/program.h | 14 ++- 8 files changed, 333 insertions(+), 139 deletions(-) diff --git a/src/array.c b/src/array.c index e464921734..b672034307 100644 --- a/src/array.c +++ b/src/array.c @@ -966,7 +966,9 @@ int array_equal_p(struct array *a, struct array *b, struct processing *p) * the type fields didn't contain types that * really aren't in the array */ - if(!(a->type_field & b->type_field)) return 0; + if(!(a->type_field & b->type_field) && + !( (a->type_field | b->type_field) & BIT_OBJECT )) + return 0; curr.pointer_a = a; curr.pointer_b = b; diff --git a/src/interpret.c b/src/interpret.c index ce568bb5eb..1275db1b35 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: interpret.c,v 1.48 1997/10/10 20:22:01 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.49 1997/10/11 06:48:23 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -1164,27 +1164,8 @@ static void eval_instruction(unsigned char *pc) } break; - CASE(F_LSH); - if(sp[-2].type != T_INT) - { - o_lsh(); - }else{ - if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n"); - sp--; - sp[-1].u.integer = sp[-1].u.integer << sp->u.integer; - } - break; - - CASE(F_RSH); - if(sp[-2].type != T_INT) - { - o_rsh(); - }else{ - if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n"); - sp--; - sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer; - } - break; + CASE(F_LSH); o_lsh(); break; + CASE(F_RSH); o_rsh(); break; COMPARISMENT(F_EQ, is_eq(sp-2,sp-1)); COMPARISMENT(F_NE,!is_eq(sp-2,sp-1)); diff --git a/src/lex.c b/src/lex.c index 21b3ac82dd..b7f66b5e47 100644 --- a/src/lex.c +++ b/src/lex.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: lex.c,v 1.27 1997/09/08 01:03:24 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.28 1997/10/11 06:48:23 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -1673,78 +1673,82 @@ static int do_lex2(int literal, YYSTYPE *yylval) case '`': { char *tmp; + int offset=2; + if(GOBBLE('`')) offset--; + if(GOBBLE('`')) offset--; + switch(GETC()) { - case '+': tmp="`+"; break; - case '/': tmp="`/"; break; - case '%': tmp="`%"; break; - case '*': tmp="`*"; break; - case '&': tmp="`&"; break; - case '|': tmp="`|"; break; - case '^': tmp="`^"; break; - case '~': tmp="`~"; break; + case '+': tmp="```+"; break; + case '/': tmp="```/"; break; + case '%': tmp="```%"; break; + case '*': tmp="```*"; break; + case '&': tmp="```&"; break; + case '|': tmp="```|"; break; + case '^': tmp="```^"; break; + case '~': tmp="```~"; break; case '<': - if(GOBBLE('<')) { tmp="`<<"; break; } - if(GOBBLE('=')) { tmp="`<="; break; } - tmp="`<"; + if(GOBBLE('<')) { tmp="```<<"; break; } + if(GOBBLE('=')) { tmp="```<="; break; } + tmp="```<"; break; case '>': - if(GOBBLE('>')) { tmp="`>>"; break; } - if(GOBBLE('=')) { tmp="`>="; break; } - tmp="`>"; + if(GOBBLE('>')) { tmp="```>>"; break; } + if(GOBBLE('=')) { tmp="```>="; break; } + tmp="```>"; break; case '!': - if(GOBBLE('=')) { tmp="`!="; break; } - tmp="`!"; + if(GOBBLE('=')) { tmp="```!="; break; } + tmp="```!"; break; case '=': - if(GOBBLE('=')) { tmp="`=="; break; } - tmp="`="; + if(GOBBLE('=')) { tmp="```=="; break; } + tmp="```="; break; case '(': if(GOBBLE(')')) { - tmp="`()"; + tmp="```()"; break; } yyerror("Illegal ` identifier."); - tmp=""; + tmp="``"; break; case '-': if(GOBBLE('>')) { - tmp="`->"; - if(GOBBLE('=')) tmp="`->="; + tmp="```->"; + if(GOBBLE('=')) tmp="```->="; }else{ - tmp="`-"; + tmp="```-"; } break; case '[': if(GOBBLE(']')) { - tmp="`[]"; - if(GOBBLE('=')) tmp="`[]="; + tmp="```[]"; + if(GOBBLE('=')) tmp="```[]="; break; } default: yyerror("Illegal ` identifier."); - tmp=""; + tmp="``"; break; } if(literal) { - yylval->str=buf; + yylval->str=tmp+offset; }else{ - yylval->string=make_shared_string(tmp); + yylval->string=make_shared_string(tmp+offset); } return F_IDENTIFIER; } diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c index ee6b6b863f..016884973d 100644 --- a/src/modules/Gmp/mpz_glue.c +++ b/src/modules/Gmp/mpz_glue.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: mpz_glue.c,v 1.22 1997/09/07 15:04:08 nisse Exp $"); +RCSID("$Id: mpz_glue.c,v 1.23 1997/10/11 06:49:19 hubbe Exp $"); #include "gmp_machine.h" #if !defined(HAVE_LIBGMP) @@ -398,6 +398,24 @@ static void mpzmod_sub(INT32 args) push_object(res); } +static void mpzmod_rsub(INT32 args) +{ + INT32 e; + struct object *res; + MP_INT *a; + + if(args!=1) + error("Gmp.mpz->``- called with more or less than one argument.\n"); + + a=get_mpz(sp-1,1); + + res = clone_object(mpzmod_program, 0); + + mpz_sub(OBTOMPZ(res), a, THIS); + pop_n_elems(args); + push_object(res); +} + static void mpzmod_div(INT32 args) { INT32 e; @@ -416,6 +434,24 @@ static void mpzmod_div(INT32 args) push_object(res); } +static void mpzmod_rdiv(INT32 args) +{ + MP_INT *a; + struct object *res; + if(!mpz_sgn(THIS)) + error("Division by zero.\n"); + + if(args!=1) + error("Gmp.mpz->``/() called with more than one argument.\n"); + + a=get_mpz(sp-1,1); + + res=clone_object(mpzmod_program,0); + mpz_fdiv_q(OBTOMPZ(res), a, THIS); + pop_n_elems(args); + push_object(res); +} + static void mpzmod_mod(INT32 args) { INT32 e; @@ -434,6 +470,25 @@ static void mpzmod_mod(INT32 args) push_object(res); } +static void mpzmod_rmod(INT32 args) +{ + MP_INT *a; + struct object *res; + if(!mpz_sgn(THIS)) + error("Modulo by zero.\n"); + + if(args!=1) + error("Gmp.mpz->``%%() called with more than one argument.\n"); + + a=get_mpz(sp-1,1); + + res=clone_object(mpzmod_program,0); + mpz_fdiv_r(OBTOMPZ(res), a, THIS); + pop_n_elems(args); + push_object(res); +} + + static void mpzmod_gcdext(INT32 args) { struct object *g, *s, *t; @@ -631,9 +686,8 @@ static void mpzmod_lsh(INT32 args) { struct object *res; if (args != 1) - error("Wrong number of arguments to Gmp.mpz->rsh.\n"); - push_string(int_type_string); - int_type_string->refs++; + error("Wrong number of arguments to Gmp.mpz->`<<.\n"); + ref_push_string(int_type_string); f_cast(); if(sp[-1].u.integer < 0) error("mpz->lsh on negative number.\n"); @@ -647,9 +701,8 @@ static void mpzmod_rsh(INT32 args) { struct object *res; if (args != 1) - error("Wrong number of arguments to Gmp.mpz->rsh.\n"); - push_string(int_type_string); - int_type_string->refs++; + error("Wrong number of arguments to Gmp.mpz->`>>.\n"); + ref_push_string(int_type_string); f_cast(); if (sp[-1].u.integer < 0) error("Gmp.mpz->rsh: Shift count must be positive.\n"); @@ -659,6 +712,39 @@ static void mpzmod_rsh(INT32 args) push_object(res); } +static void mpzmod_rlsh(INT32 args) +{ + struct object *res; + INT32 i; + if (args != 1) + error("Wrong number of arguments to Gmp.mpz->``<<.\n"); + get_mpz(sp-1,1); + i=mpz_get_si(THIS); + if(i < 0) + error("mpz->``<< on negative number.\n"); + + res = clone_object(mpzmod_program, 0); + mpz_mul_2exp(OBTOMPZ(res), OBTOMPZ(sp[-1].u.object), i); + pop_n_elems(args); + push_object(res); +} + +static void mpzmod_rrsh(INT32 args) +{ + struct object *res; + INT32 i; + if (args != 1) + error("Wrong number of arguments to Gmp.mpz->``>>.\n"); + get_mpz(sp-1,1); + i=mpz_get_si(THIS); + if(i < 0) + error("mpz->``>> on negative number.\n"); + res = clone_object(mpzmod_program, 0); + mpz_fdiv_q_2exp(OBTOMPZ(res), OBTOMPZ(sp[-1].u.object), i); + pop_n_elems(args); + push_object(res); +} + static void mpzmod_powm(INT32 args) { struct object *res; @@ -759,17 +845,26 @@ void pike_module_init(void) #define MPZ_BINOP_TYPE ("function(" MPZ_ARG_TYPE "...:object)") add_function("`+",mpzmod_add,MPZ_BINOP_TYPE,0); + add_function("``+",mpzmod_add,MPZ_BINOP_TYPE,0); add_function("`-",mpzmod_sub,MPZ_BINOP_TYPE,0); + add_function("``-",mpzmod_rsub,MPZ_BINOP_TYPE,0); add_function("`*",mpzmod_mul,MPZ_BINOP_TYPE,0); + add_function("``*",mpzmod_mul,MPZ_BINOP_TYPE,0); add_function("`/",mpzmod_div,MPZ_BINOP_TYPE,0); + add_function("``/",mpzmod_rdiv,MPZ_BINOP_TYPE,0); add_function("`%",mpzmod_mod,MPZ_BINOP_TYPE,0); + add_function("``%",mpzmod_rmod,MPZ_BINOP_TYPE,0); add_function("`&",mpzmod_and,MPZ_BINOP_TYPE,0); + add_function("``&",mpzmod_and,MPZ_BINOP_TYPE,0); add_function("`|",mpzmod_or,MPZ_BINOP_TYPE,0); + add_function("``|",mpzmod_or,MPZ_BINOP_TYPE,0); add_function("`~",mpzmod_compl,"function(:object)",0); #define MPZ_SHIFT_TYPE "function(int|float|object:object)" add_function("`<<",mpzmod_lsh,MPZ_SHIFT_TYPE,0); add_function("`>>",mpzmod_rsh,MPZ_SHIFT_TYPE,0); + add_function("``<<",mpzmod_rlsh,MPZ_SHIFT_TYPE,0); + add_function("``>>",mpzmod_rrsh,MPZ_SHIFT_TYPE,0); #define MPZ_CMPOP_TYPE ("function(" MPZ_ARG_TYPE ":int)") diff --git a/src/modules/Gmp/testsuite.in b/src/modules/Gmp/testsuite.in index dd277e5bc5..6c8c34e3d3 100644 --- a/src/modules/Gmp/testsuite.in +++ b/src/modules/Gmp/testsuite.in @@ -15,18 +15,27 @@ cond( [[ master()->resolv("Gmp")->mpz ]], test_eq(Gmp.mpz("17") != "foo", 1) test_true(catch(Gmp.mpz("17") < "foo")) - test_eq(clone(Gmp.mpz,99)+1,100) - test_eq(clone(Gmp.mpz,100)*10,1000) - test_eq(clone(Gmp.mpz,"100")*10.0,1000) - test_eq(clone(Gmp.mpz,100.0)*clone(Gmp.mpz,3),300) - test_eq(clone(Gmp.mpz,100.0)/4,25) - test_eq(clone(Gmp.mpz,42)%10,2) - test_eq(clone(Gmp.mpz,10)<<1,20) - test_eq(clone(Gmp.mpz,10)>>1,5) - test_eq(clone(Gmp.mpz,66)+11,77) - test_eq(clone(Gmp.mpz,66)-11,55) - test_eq(clone(Gmp.mpz,17)&18,16) - test_eq(clone(Gmp.mpz,17)|7,23) + define([[test_binop]],[[ + test_eq(Gmp.mpz($1) $2 $3, $4) + test_eq(Gmp.mpz($1) $2 $3.0, $4) + test_eq(Gmp.mpz($1) $2 Gmp.mpz($3), $4) + test_eq($1 $2 Gmp.mpz($3), $4) + test_eq($1.0 $2 Gmp.mpz($3), $4) + test_eq($1.0 $2 Gmp.mpz($3), $4) + test_eq($1 $2 $3,Gmp.mpz($4)) + ]]) + + test_binop(99,+,1,100) + test_binop(100,*,10,1000) + test_binop(100,/,4,25) + test_binop(103,/,4,25) + test_binop(10,<<,1,20) + test_binop(10,>>,1,5) + test_binop(66,+,11,77) + test_binop(66,-,11,55) + test_binop(17,|,7,23) + test_binop(17,&,18,16) + test_eq(-clone(Gmp.mpz,17),-17) test_eq((~clone(Gmp.mpz,17)) & 255,238) test_true(stringp((string)clone(Gmp.mpz,17))) @@ -56,19 +65,25 @@ cond( [[ master()->resolv("Gmp")->mpz ]], mpz_test_type2(1,2) mpz_test_type2(-2,1) - mpz_test_true(catch(Gmp.mpz("abcd", 47))) - mpz_test_true(catch(Gmp.mpz(-17)->digits(256))) - mpz_test_eq(Gmp.mpz(4711)->size(2), 13) - mpz_test_true(catch(Gmp.mpz(17) + 18 + "19")) - mpz_test_true(catch(Gmp.mpz(17) - 18 - "19")) - mpz_test_true(catch(Gmp.mpz(17) / 0)) - mpz_test_true(catch(Gmp.mpz(49) % 0)) - mpz_test_eq(Gmp.mpz(0)->pow(0), 1) - mpz_test_true(equal(Gmp.mpz(13)->gcdext(19), ({1, 3, -2}))) - mpz_test_eq(Gmp.mpz(17)->invert(4711), 2217) - mpz_test_true(catch(Gmp.mpz(4711)->invert(0))) - mpz_test_true(catch(Gmp.mpz(7)->invert(4711))) - mpz_test_true(catch(Gmp.mpz(2)->powm(47, 0))) - + test_true(catch(Gmp.mpz("abcd", 47))) + test_true(catch(Gmp.mpz(-17)->digits(256))) + test_eq(Gmp.mpz(4711)->size(2), 13) + test_true(catch(Gmp.mpz(17) + 18 + "19")) + test_true(catch(Gmp.mpz(17) - 18 - "19")) + test_true(catch(Gmp.mpz(17) / 0)) + test_true(catch(Gmp.mpz(49) % 0)) + test_eq(Gmp.mpz(0)->pow(0), 1) + test_true(equal(Gmp.mpz(13)->gcdext(19), ({1, 3, -2}))) + test_eq(Gmp.mpz(17)->invert(4711), 2217) + test_true(catch(Gmp.mpz(4711)->invert(0))) + test_true(catch(Gmp.mpz(7)->invert(4711))) + test_true(catch(Gmp.mpz(2)->powm(47, 0))) + test_any([[object o=Gmp.mpz(1); o++; return o;]],2) + test_any([[object o=Gmp.mpz(1); return o++;]],1) + test_any([[object o=Gmp.mpz(1); return ++o;]],2) + test_any([[object o=Gmp.mpz(1); o++;o++;o++;o++;o++;o++;o++;o++;o++; return o]],10) + test_any([[object o=Gmp.mpz(2); o--; return o;]],1) + test_any([[object o=Gmp.mpz(2); return --o;]],1) + test_any([[object o=Gmp.mpz(2); return o--;]],2) ]]); diff --git a/src/operators.c b/src/operators.c index 4ee7cf33da..75f4dc8a4b 100644 --- a/src/operators.c +++ b/src/operators.c @@ -5,7 +5,7 @@ \*/ #include <math.h> #include "global.h" -RCSID("$Id: operators.c,v 1.19 1997/10/10 20:19:58 hubbe Exp $"); +RCSID("$Id: operators.c,v 1.20 1997/10/11 06:48:24 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "multiset.h" @@ -68,18 +68,55 @@ void f_add(INT32 args) switch(types) { default: - if(args) + if(!args) { - switch(sp[-args].type) + error("Too few arguments to `+()\n"); + }else{ + if(types & BIT_OBJECT) { - case T_OBJECT: - CALL_OPERATOR(LFUN_ADD,args); - return; + if(sp[-args].type == T_OBJECT && + sp[-args].u.object->prog && + sp[-args].u.object->prog->lfuns[LFUN_ADD] != -1) + { + apply_lfun(sp[-args].u.object, LFUN_ADD, args-1); + free_svalue(sp-2); + sp[-2]=sp[-1]; + sp--; + return; + } + for(e=1;e<args;e++) + { + if(sp[e-args].type == T_OBJECT && + sp[e-args].u.object->prog && + sp[e-args].u.object->prog->lfuns[LFUN_RADD] != -1) + { + struct svalue *tmp=sp+e-args; + check_stack(e); + assign_svalues_no_free(sp, sp-args, e, -1); + sp+=e; + apply_lfun(tmp->u.object, LFUN_RADD, e); + if(args - e > 2) + { + assign_svalue(tmp, sp-1); + pop_stack(); + f_add(args - e); + assign_svalue(sp-e-1,sp-1); + pop_n_elems(e); + }else{ + assign_svalue(sp-args-1,sp-1); + pop_n_elems(args); + } + return; + } + } + } + } + switch(sp[-args].type) + { case T_PROGRAM: case T_FUNCTION: error("Bad argument 1 to summation\n"); - } } error("Incompatible types to sum() or +\n"); return; /* compiler hint */ @@ -335,27 +372,58 @@ static int generate_comparison(node *n) static int float_promote(void) { - if(sp[-2].type==T_INT) + if(sp[-2].type==T_INT && sp[-1].type==T_FLOAT) { sp[-2].u.float_number=(FLOAT_TYPE)sp[-2].u.integer; sp[-2].type=T_FLOAT; + return 1; } - - if(sp[-1].type==T_INT) + else if(sp[-1].type==T_INT && sp[-2].type==T_FLOAT) { sp[-1].u.float_number=(FLOAT_TYPE)sp[-1].u.integer; sp[-1].type=T_FLOAT; + return 1; + } + return 0; +} + +static int call_lfun(int left, int right) +{ + if(sp[-2].type == T_OBJECT && + sp[-2].u.object->prog && + sp[-2].u.object->prog->lfuns[left] != -1) + { + apply_lfun(sp[-2].u.object, left, 1); + free_svalue(sp-2); + sp[-2]=sp[-1]; + sp--; + return 1; } - return sp[-2].type == sp[-1].type; + if(sp[-1].type == T_OBJECT && + sp[-1].u.object->prog && + sp[-1].u.object->prog->lfuns[right] != -1) + { + push_svalue(sp-2); + apply_lfun(sp[-2].u.object, right, 1); + free_svalue(sp-3); + sp[-3]=sp[-1]; + sp--; + pop_stack(); + return 1; + } + + return 0; } void o_subtract(void) { - if (sp[-2].type != sp[-1].type && - !float_promote() && - sp[-2].type != T_OBJECT) + if (sp[-2].type != sp[-1].type && !float_promote()) + { + if(call_lfun(LFUN_SUBTRACT, LFUN_RSUBTRACT)) + return; error("Subtract on different types.\n"); + } switch(sp[-2].type) { @@ -451,9 +519,13 @@ static int generate_minus(node *n) void o_and(void) { - if(sp[-1].type != sp[-2].type && - sp[-2].type != T_OBJECT) + if(sp[-1].type != sp[-2].type) + { + if(call_lfun(LFUN_AND, LFUN_RAND)) + return; + error("Bitwise and on different types.\n"); + } switch(sp[-2].type) { @@ -587,9 +659,13 @@ static int generate_and(node *n) void o_or(void) { - if(sp[-1].type != sp[-2].type && - sp[-2].type != T_OBJECT) + if(sp[-1].type != sp[-2].type) + { + if(call_lfun(LFUN_OR, LFUN_ROR)) + return; + error("Bitwise or on different types.\n"); + } switch(sp[-2].type) { @@ -688,9 +764,12 @@ static int generate_or(node *n) void o_xor(void) { - if(sp[-1].type != sp[-2].type && - sp[-2].type != T_OBJECT) + if(sp[-1].type != sp[-2].type) + { + if(call_lfun(LFUN_XOR, LFUN_RXOR)) + return; error("Bitwise xor on different types.\n"); + } switch(sp[-2].type) { @@ -788,17 +867,15 @@ static int generate_xor(node *n) void o_lsh(void) { - if(sp[-2].type != T_INT) + if(sp[-1].type != T_INT || sp[-2].type != T_INT) { - if(sp[-2].type == T_OBJECT) - { - CALL_OPERATOR(LFUN_LSH,2); + if(call_lfun(LFUN_LSH, LFUN_RLSH)) return; - } - error("Bad argument 1 to <<\n"); + if(sp[-2].type != T_INT) + error("Bad argument 1 to <<\n"); + error("Bad argument 2 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; } @@ -823,16 +900,14 @@ static int generate_lsh(node *n) void o_rsh(void) { - if(sp[-2].type != T_INT) + if(sp[-2].type != T_INT || sp[-1].type != T_INT) { - if(sp[-2].type == T_OBJECT) - { - CALL_OPERATOR(LFUN_RSH,2); + if(call_lfun(LFUN_RSH, LFUN_RRSH)) return; - } - error("Bad argument 1 to >>\n"); + if(sp[-2].type != T_INT) + error("Bad argument 1 to >>\n"); + error("Bad argument 2 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; } @@ -905,11 +980,8 @@ void o_multiply(void) return; default: - if(sp[-2].type == T_OBJECT) - { - CALL_OPERATOR(LFUN_MULTIPLY,2); + if(call_lfun(LFUN_MULTIPLY, LFUN_RMULTIPLY)) return; - } error("Bad arguments to multiply.\n"); } @@ -952,10 +1024,12 @@ static int generate_multiply(node *n) void o_divide(void) { - if(sp[-2].type!=sp[-1].type && - !float_promote() && - sp[-2].type != T_OBJECT) + if(sp[-2].type!=sp[-1].type && !float_promote()) + { + if(call_lfun(LFUN_DIVIDE, LFUN_RDIVIDE)) + return; error("Division on different types.\n"); + } switch(sp[-2].type) { @@ -1030,10 +1104,13 @@ static int generate_divide(node *n) void o_mod(void) { - if(sp[-2].type != sp[-1].type && - !float_promote() && - sp[-2].type != T_OBJECT) + if(sp[-2].type != sp[-1].type && !float_promote()) + { + if(call_lfun(LFUN_MOD, LFUN_RMOD)) + return; + error("Modulo on different types.\n"); + } switch(sp[-2].type) { @@ -1357,11 +1434,11 @@ void init_operators(void) 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_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(multiset...:multiset)",OPT_TRY_OPTIMIZE,optimize_binary,generate_sum); + add_efun2("`+",f_add,"!function(!object...:mixed)&function(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(multiset...:multiset)",OPT_TRY_OPTIMIZE,optimize_binary,generate_sum); - add_efun2("`-",f_minus,"function(object,mixed...:mixed)|function(int:int)|function(float:float)|function(array,array:array)|function(mapping,mapping:mapping)|function(multiset,multiset:multiset)|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_minus,"!function(!object...:mixed)&function(mixed...:mixed)|function(int:int)|function(float:float)|function(array,array:array)|function(mapping,mapping:mapping)|function(multiset,multiset:multiset)|function(float|int,float:float)|function(float,int:float)|function(int,int:int)|function(string,string:string)",OPT_TRY_OPTIMIZE,0,generate_minus); -#define LOG_TYPE "function(object,mixed...:mixed)|function(int...:int)|function(mapping...:mapping)|function(multiset...:multiset)|function(array...:array)|function(string...:string)" +#define LOG_TYPE "function(mixed,object...:mixed)|function(object,mixed...:mixed)|function(int...:int)|function(mapping...:mapping)|function(multiset...:multiset)|function(array...:array)|function(string...:string)" add_efun2("`&",f_and,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_and); @@ -1370,16 +1447,16 @@ void init_operators(void) add_efun2("`^",f_xor,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_xor); -#define SHIFT_TYPE "function(object,mixed:mixed)|function(int,int:int)" +#define SHIFT_TYPE "function(object,mixed:mixed)|function(mixed,object:mixed)|function(int,int:int)" 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(array(array),array:array)|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_multiply,"!function(!object...:mixed)&function(mixed...:mixed)|function(array(array),array:array)|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(array,array:array(array))|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_divide,"function(mixed,object:mixed)|function(array,array:array(array))|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_mod,"function(mixed,object:mixed)|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)|function(string:string)",OPT_TRY_OPTIMIZE,0,generate_compl); add_efun2("sizeof", f_sizeof, "function(string|multiset|array|mapping|object:int)",0,0,generate_sizeof); diff --git a/src/program.c b/src/program.c index d985970bc0..416c531607 100644 --- a/src/program.c +++ b/src/program.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: program.c,v 1.42 1997/09/22 01:01:18 hubbe Exp $"); +RCSID("$Id: program.c,v 1.43 1997/10/11 06:48:25 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -78,6 +78,16 @@ char *lfun_names[] = { "_indices", "_values", "`()", + "``+", + "``-", + "``&", + "``|", + "``^", + "``<<", + "``>>", + "``*", + "``/", + "``%", }; struct program *first_program = 0; diff --git a/src/program.h b/src/program.h index 243ccde548..7fd0708b2a 100644 --- a/src/program.h +++ b/src/program.h @@ -37,8 +37,18 @@ #define LFUN__INDICES 25 #define LFUN__VALUES 26 #define LFUN_CALL 27 - -#define NUM_LFUNS 28 +#define LFUN_RADD 28 +#define LFUN_RSUBTRACT 29 +#define LFUN_RAND 30 +#define LFUN_ROR 31 +#define LFUN_RXOR 32 +#define LFUN_RLSH 33 +#define LFUN_RRSH 34 +#define LFUN_RMULTIPLY 35 +#define LFUN_RDIVIDE 36 +#define LFUN_RMOD 37 + +#define NUM_LFUNS 38 extern char *lfun_names[]; -- GitLab