diff --git a/src/las.c b/src/las.c index f4256117201f0526fc75b23ab229d15c8284bb31..41d9d2dc2ee84727c41f700fe14dcfea4d647ca1 100644 --- a/src/las.c +++ b/src/las.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: las.c,v 1.50 1998/02/01 04:01:34 hubbe Exp $"); +RCSID("$Id: las.c,v 1.51 1998/02/23 23:24:02 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -1424,6 +1424,7 @@ void fix_type_field(node *n) { struct pike_string *s; struct pike_string *f; + INT32 max_args,args; push_type(T_MIXED); /* match any return type, even void */ push_type(T_VOID); /* not varargs */ push_type(T_MANY); @@ -1432,6 +1433,8 @@ void fix_type_field(node *n) s=pop_type(); f=CAR(n)->type?CAR(n)->type:mixed_type_string; n->type=check_call(s,f); + args=count_arguments(s); + max_args=get_max_args(f); if(!n->type) { @@ -1447,8 +1450,13 @@ void fix_type_field(node *n) switch(CAR(n)->u.sval.type) { case T_FUNCTION: - name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog, - CAR(n)->u.sval.subtype)->name->str; + if(CAR(n)->u.sval.subtype == FUNCTION_BUILTIN) + { + name=CAR(n)->u.sval.u.efun->name->str; + }else{ + name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog, + CAR(n)->u.sval.subtype)->name->str; + } break; case T_ARRAY: @@ -1463,12 +1471,17 @@ void fix_type_field(node *n) name="`() (function call)"; break; } + break; default: name="unknown function"; } - if(max_correct_args == count_arguments(s)) + if(max_args < args) + { + my_yyerror("To many arguments to %s.\n",name); + } + else if(max_correct_args == args) { my_yyerror("To few arguments to %s.\n",name); }else{ diff --git a/src/modules/math/math.c b/src/modules/math/math.c index 3641a11bbb7d31fd0ac4e1a69e60d3424ce54ddf..28fef483b9c8ef394da52a1a5aaa44f68b297331 100644 --- a/src/modules/math/math.c +++ b/src/modules/math/math.c @@ -141,16 +141,21 @@ void f_ceil(INT32 args) void f_min(INT32 args) { - check_all_args("min",args,BIT_MIXED,BIT_MIXED,0); - if(args<2) error("Too few arguments to min()\n"); - if(is_gt(sp-args,sp-args+1)) assign_svalue(sp-args,sp-args+1); + INT32 i; + if(!args) error("Too few arguments to min()\n"); + for(i=args-2;i>=0;i--) + if(is_gt(sp-args+i,sp-args+1+i)) + assign_svalue(sp-args+i,sp-args+1+i); pop_n_elems(args-1); } void f_max(INT32 args) { - check_all_args("max",args,BIT_MIXED,BIT_MIXED,0); - if(is_lt(sp-args,sp-args+1)) assign_svalue(sp-args,sp-args+1); + INT32 i; + if(!args) error("Too few arguments to max()\n"); + for(i=args-2;i>=0;i--) + if(is_lt(sp-args+i,sp-args+1+i)) + assign_svalue(sp-args+i,sp-args+1+i); pop_n_elems(args-1); } @@ -206,8 +211,15 @@ void pike_module_init(void) add_efun("floor",f_floor,"function(float:float)",0); add_efun("ceil",f_ceil,"function(float:float)",0); - add_efun("max",f_max,"function(mixed,mixed:mixed)",0); - add_efun("min",f_min,"function(mixed,mixed:mixed)",0); +#define CMP_TYPE \ + "!function(!object...:mixed)&function(mixed...:mixed)|" \ + "function(int...:int)|" \ + "function(float...:float)|" \ + "function(string...:string)|" \ + "!function(int...:mixed)&!function(float...:mixed)&function(int|float...:int|float)" + + add_efun("max",f_max,CMP_TYPE,0); + add_efun("min",f_min,CMP_TYPE,0); add_efun("abs",f_abs,"function(float|int|object:float|int|object)",0); add_efun("sgn",f_sgn,"function(mixed,mixed|void:int)",0); } diff --git a/src/operators.c b/src/operators.c index 9dec0f1529aba787422a56b84c9b523cfc78693d..9bd585357e955927c7affd5d0711fdab7e9cdf64 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.24 1998/02/20 01:00:42 hubbe Exp $"); +RCSID("$Id: operators.c,v 1.25 1998/02/23 23:24:03 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "multiset.h" @@ -25,25 +25,39 @@ RCSID("$Id: operators.c,v 1.24 1998/02/20 01:00:42 hubbe Exp $"); #include "object.h" #include "pike_types.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); \ - push_int(i); \ +#define COMPARISON(ID,NAME,FUN) \ +void ID(INT32 args) \ +{ \ + int i; \ + switch(args) \ + { \ + case 0: case 1: \ + error("Too few arguments to %s\n",NAME); \ + case 2: \ + i=FUN (sp-2,sp-1); \ + pop_n_elems(2); \ + push_int(i); \ + break; \ + default: \ + for(i=1;i<args;i++) \ + if(! ( FUN (sp-args+i-1, sp-args+i))) \ + break; \ + pop_n_elems(args); \ + push_int(i==args); \ + } \ } -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)) +void f_ne(INT32 args) +{ + f_eq(args); + o_not(); +} + +COMPARISON(f_eq,"`==", is_eq) +COMPARISON(f_lt,"`<" , is_lt) +COMPARISON(f_le,"`<=",!is_gt) +COMPARISON(f_gt,"`>" , is_gt) +COMPARISON(f_ge,"`>=",!is_lt) #define CALL_OPERATOR(OP, args) \ @@ -493,10 +507,22 @@ void f_minus(INT32 args) { switch(args) { - case 0: error("Too few arguments to `-\n"); - case 1: o_negate(); break; - case 2: o_subtract(); break; - default: error("Too many arguments to `-\n"); + case 0: error("Too few arguments to `-\n"); + case 1: o_negate(); break; + case 2: o_subtract(); break; + default: + { + INT32 e; + struct svalue *s=sp-args; + push_svalue(s); + for(e=1;e<args;e++) + { + push_svalue(s+e); + o_subtract(); + } + assign_svalue(s,sp-1); + pop_n_elems(sp-s-1); + } } } @@ -1287,9 +1313,25 @@ void o_divide(void) void f_divide(INT32 args) { - if(args != 2) - error("Bad number of args to `/\n"); - o_divide(); + switch(args) + { + case 0: + case 1: error("Too few arguments to `/\n"); + case 2: o_divide(); break; + default: + { + INT32 e; + struct svalue *s=sp-args; + push_svalue(s); + for(e=1;e<args;e++) + { + push_svalue(s+e); + o_divide(); + } + assign_svalue(s,sp-1); + pop_n_elems(sp-s-1); + } + } } static int generate_divide(node *n) @@ -1669,11 +1711,11 @@ void init_operators(void) add_efun2("`->",f_arrow, "function(array(object|mapping|multiset|array)|object|mapping|multiset,string:mixed)",OPT_TRY_OPTIMIZE,0,0); - 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_eq,"function(mixed...:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); + add_efun2("`!=",f_ne,"function(mixed...:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); add_efun2("`!",f_not,"function(mixed:int)",OPT_TRY_OPTIMIZE,0,generate_not); -#define CMP_TYPE "function(object,mixed:int)|function(mixed,object:int)|function(int|float,int|float:int)|function(string,string:int)" +#define CMP_TYPE "!function(!object...:mixed)&function(mixed...:int)|function(int|float...:int)|function(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); @@ -1708,13 +1750,11 @@ void init_operators(void) OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); add_efun2("`/",f_divide, - "function(mixed,object:mixed)|" - "function(array,array|int|float:array(array))|" - "function(object,mixed:mixed)|" - "function(int,int:int)|" - "function(float|int,float:float)|" - "function(float,int:float)|" - "function(string,string|int|float:string*)", + "!function(!object...:mixed)&function(mixed...:mixed)|" + "function(int,int...:int)|" + "!function(int...:mixed)&function(float|int...:float)|" + "function(array,array|int|float...:array(array))|" + "function(string,string|int|float...:array(string))", OPT_TRY_OPTIMIZE,0,generate_divide); 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); diff --git a/src/pike_types.c b/src/pike_types.c index 16a0aa58b04d42c30ce24016fe2c6ab6c5398315..b1b12a420b9e37feb1d3a6c0a86ef67501bcaa7f 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: pike_types.c,v 1.31 1998/02/20 00:55:23 hubbe Exp $"); +RCSID("$Id: pike_types.c,v 1.32 1998/02/23 23:24:04 hubbe Exp $"); #include <ctype.h> #include "svalue.h" #include "pike_types.h" @@ -645,6 +645,7 @@ TYPE_T compile_type_to_runtime_type(struct pike_string *s) #define A_EXACT 1 #define B_EXACT 2 +#define NO_MAX_ARGS 4 /* * match two type strings, return zero if they don't match, and return @@ -673,7 +674,7 @@ static char *low_match_types(char *a,char *b, int flags) return low_match_types(a,b,flags); case T_NOT: - if(low_match_types(a+1,b,flags | B_EXACT)) + if(low_match_types(a+1,b,flags | B_EXACT | NO_MAX_ARGS)) return 0; return a; } @@ -695,7 +696,7 @@ static char *low_match_types(char *a,char *b, int flags) return low_match_types(a,b,flags); case T_NOT: - if(low_match_types(a,b+1, flags | A_EXACT)) + if(low_match_types(a,b+1, flags | A_EXACT | NO_MAX_ARGS)) return 0; return a; } @@ -763,9 +764,10 @@ static char *low_match_types(char *a,char *b, int flags) b+=type_length(b); } - if(!low_match_types(a_tmp, b_tmp, flags)) return 0; + if(!low_match_types(a_tmp, b_tmp, flags | NO_MAX_ARGS)) return 0; if(++correct_args > max_correct_args) - max_correct_args=correct_args; + if(!(flags & NO_MAX_ARGS)) + max_correct_args=correct_args; } /* check the 'many' type */ a++; @@ -775,8 +777,10 @@ static char *low_match_types(char *a,char *b, int flags) a+=type_length(a); b+=type_length(b); }else{ - if(!low_match_types(a,b,flags)) return 0; + if(!low_match_types(a,b,flags | NO_MAX_ARGS)) return 0; } + if(!(flags & NO_MAX_ARGS)) + max_correct_args=0x7fffffff; /* check the returntype */ if(!low_match_types(a,b,flags)) return 0; break; @@ -1087,29 +1091,52 @@ int check_indexing(struct pike_string *type, return low_check_indexing(type->str, index_type->str, n); } +static int low_count_arguments(char *q) +{ + int num,num2; + + switch(EXTRACT_UCHAR(q++)) + { + case T_OR: + num=low_count_arguments(q); + num2=low_count_arguments(q+type_length(q)); + if(num<0 && num2>0) return num; + if(num2<0 && num>0) return num2; + if(num2<0 && num<0) return ~num>~num2?num:num2; + return num>num2?num:num2; + + case T_AND: + num=low_count_arguments(q); + num2=low_count_arguments(q+type_length(q)); + if(num<0 && num2>0) return num2; + if(num2<0 && num>0) return num; + if(num2<0 && num<0) return ~num<~num2?num:num2; + return num<num2?num:num2; + + default: return MAX_LOCAL; + + case T_FUNCTION: + num=0; + while(EXTRACT_UCHAR(q)!=T_MANY) + { + num++; + q+=type_length(q); + } + q++; + if(EXTRACT_UCHAR(q)!=T_VOID) return ~num; + return num; + } +} + /* Count the number of arguments for a funciton type. * return -1-n if the function can take number of arguments * >= n (varargs) */ int count_arguments(struct pike_string *s) { - int num; - char *q; - CHECK_TYPE(s); - q=s->str; - if(EXTRACT_UCHAR(q) != T_FUNCTION) return MAX_LOCAL; - q++; - num=0; - while(EXTRACT_UCHAR(q)!=T_MANY) - { - num++; - q+=type_length(q); - } - q++; - if(EXTRACT_UCHAR(q)!=T_VOID) return ~num; - return num; + return low_count_arguments(s->str); } struct pike_string *check_call(struct pike_string *args, @@ -1129,6 +1156,17 @@ struct pike_string *check_call(struct pike_string *args, } } +INT32 get_max_args(struct pike_string *type) +{ + INT32 ret,tmp=max_correct_args; + CHECK_TYPE(type); + type=check_call(function_type_string, type); + if(type) free_string(type); + ret=max_correct_args; + max_correct_args=tmp; + return tmp; +} + struct pike_string *get_type_of_svalue(struct svalue *s) { struct pike_string *ret; diff --git a/src/pike_types.h b/src/pike_types.h index 0c449555f2e944e975de6559cf5f707b12b1b755..1f184c9071d4338834704eb6d52d92cca5d13dfb 100644 --- a/src/pike_types.h +++ b/src/pike_types.h @@ -85,6 +85,7 @@ int check_indexing(struct pike_string *type, int count_arguments(struct pike_string *s); struct pike_string *check_call(struct pike_string *args, struct pike_string *type); +INT32 get_max_args(struct pike_string *type); struct pike_string *get_type_of_svalue(struct svalue *s); char *get_name_of_type(int t); void cleanup_pike_types(void);