diff --git a/src/language.yacc b/src/language.yacc index 342ec8220e6c26ee298eda93af77913880f9e022..0ccc0def67991c1d3649d06bc82f3b94078d40eb 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -156,7 +156,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.24 1997/02/14 04:45:57 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.25 1997/02/18 05:13:34 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -181,8 +181,6 @@ RCSID("$Id: language.yacc,v 1.24 1997/02/14 04:45:57 hubbe Exp $"); #define YYDEBUG 1 #endif -static void push_locals(); -static void pop_locals(); void free_all_local_names(); void add_local_name(struct pike_string *,struct pike_string *); @@ -524,8 +522,6 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' int e; if($9) { - union idptr tmp; - int args, vargs; for(e=0; e<$6; e++) { if(!local_variables->variable[e].name || @@ -534,25 +530,8 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' my_yyerror("Missing name for argument %d",e); } } - - tmp.offset=PC; - args=count_arguments($<string>8); - if(args < 0) - { - args=~args; - vargs=IDENTIFIER_VARARGS; - }else{ - vargs=0; - } - ins_byte(local_variables->max_number_of_locals, A_PROGRAM); - ins_byte(args, A_PROGRAM); - dooptcode($4, $9, $6); - - define_function($4, - $<string>8, - $1, - IDENTIFIER_PIKE_FUNCTION | vargs, - &tmp); + + dooptcode($4, $9, $<string>8, $1); } if(local_variables->current_return_type) { @@ -858,8 +837,7 @@ lambda: F_LAMBDA { struct pike_string *type; char buf[40]; - int f,e,args,vargs; - union idptr func; + int f,e; struct pike_string *name; setup_fake_program(); @@ -884,28 +862,15 @@ lambda: F_LAMBDA push_type(T_FUNCTION); type=pop_type(); - func.offset=PC; - - args=count_arguments(type); - if(args < 0) - { - args=~args; - vargs=IDENTIFIER_VARARGS; - }else{ - vargs=0; - } - ins_byte(local_variables->max_number_of_locals, A_PROGRAM); - ins_byte(args, A_PROGRAM); sprintf(buf,"__lambda_%ld", (long)fake_program.num_identifier_references); name=make_shared_string(buf); - dooptcode(name,mknode(F_ARG_LIST,$6,mknode(F_RETURN,mkintnode(0),0)),$4); - f=define_function(name, - type, - 0, - IDENTIFIER_PIKE_FUNCTION | vargs, - &func); + + f=dooptcode(name, + mknode(F_ARG_LIST,$6,mknode(F_RETURN,mkintnode(0),0)), + type, + 0); free_string(name); free_string(type); pop_locals(); @@ -1413,29 +1378,3 @@ void free_all_local_names() local_variables->max_number_of_locals = 0; } -static void push_locals() -{ - struct locals *l; - l=ALLOC_STRUCT(locals); - l->current_type=0; - l->current_return_type=0; - l->next=local_variables; - l->current_number_of_locals=0; - l->max_number_of_locals=0; - local_variables=l; -} - -static void pop_locals() -{ - struct locals *l; - free_all_local_names(); - l=local_variables->next; - if(local_variables->current_type) - free_string(local_variables->current_type); - if(local_variables->current_return_type) - free_string(local_variables->current_return_type); - free((char *)local_variables); - - local_variables=l; - /* insert check if ( local->next == parent locals ) here */ -} diff --git a/src/las.c b/src/las.c index 6ac6d40c9ff086aa32256d31036d437d8bbc9c1a..5e66d7fd3d5d7755416b6aaef7bdd71539ef590e 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.20 1997/02/11 07:10:54 hubbe Exp $"); +RCSID("$Id: las.c,v 1.21 1997/02/18 05:13:35 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -1882,14 +1882,123 @@ static node *eval(node *n) INT32 last_function_opt_info; -void dooptcode(struct pike_string *name,node *n, int args) +static int stupid_args(node *n, int expected,int vargs) { + if(!n) return expected; + switch(n->token) + { + case F_PUSH_ARRAY: + if(!vargs) return -1; + + if(stupid_args(CAR(n), expected,vargs) == expected+1) + return 65535; + return -1; + + case F_ARG_LIST: + expected=stupid_args(CAR(n), expected,vargs); + if(expected==-1) return -1; + return stupid_args(CDR(n), expected,vargs); + case F_LOCAL: + return n->u.number==expected ? expected + 1 : -1; + default: + return -1; + } +} + +static is_null_branch(node *n) +{ + if(!n) return 1; + if(n->token==F_CAST && n->type==void_type_string) + return is_null_branch(CAR(n)); + if(n->token==F_ARG_LIST) + return is_null_branch(CAR(n)) && is_null_branch(CDR(n)); + return 0; +} + +static struct svalue *is_stupid_func(node *n, + int args, + int vargs) +{ + node *a,*b; + int tmp; + while(1) + { + if(!n) return 0; + + if(n->token == F_ARG_LIST) + { + if(is_null_branch(CAR(n))) + n=CDR(n); + else + n=CAR(n); + continue; + } + + if(n->token == F_CAST && n->type==void_type_string) + { + n=CAR(n); + continue; + } + break; + } + + if(n->token != F_RETURN) return 0; + n=CAR(n); + + if(n->token != F_APPLY) return 0; + + tmp=stupid_args(CDR(n),0,vargs); + if(!(vargs?tmp==65535:tmp==args)) return 0; + + n=CAR(n); + if(n->token != F_CONSTANT) return 0; + return &n->u.sval; +} + +int dooptcode(struct pike_string *name, + node *n, + struct pike_string *type, + int modifiers) +{ + union idptr tmp; + int args, vargs, ret; + struct svalue *foo; + #ifdef DEBUG if(a_flag > 1) fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC); #endif last_function_opt_info=OPT_SIDE_EFFECT; + + args=count_arguments(type); + if(args < 0) + { + args=~args; + vargs=IDENTIFIER_VARARGS; + }else{ + vargs=0; + } n=mknode(F_ARG_LIST,n,0); + + if(foo=is_stupid_func(n, args, vargs)) + { + if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN) + { + tmp.c_fun=foo->u.efun->function; + ret=define_function(name, + type, + modifiers, + IDENTIFIER_C_FUNCTION | vargs, + &tmp); + free_node(n); + return ret; + } + } + + tmp.offset=PC; + ins_byte(local_variables->max_number_of_locals, A_PROGRAM); + ins_byte(args, A_PROGRAM); + #ifdef DEBUG if(a_flag > 2) { @@ -1900,9 +2009,16 @@ void dooptcode(struct pike_string *name,node *n, int args) if(!num_parse_error) { do_code_block(n); - last_function_opt_info = n->tree_info; } + + ret=define_function(name, + type, + modifiers, + IDENTIFIER_PIKE_FUNCTION | vargs, + &tmp); + free_node(n); + return ret; } INT32 get_opt_info() { return last_function_opt_info; } diff --git a/src/las.h b/src/las.h index c3924ec0dcde302ba9bae975522099738d3f1be9..078670474766d8fde6c66d094b511c50d5441205 100644 --- a/src/las.h +++ b/src/las.h @@ -110,7 +110,10 @@ struct used_vars; void fix_type_field(node *n); struct timer_oflo; int eval_low(node *n); -void dooptcode(struct pike_string *name,node *n, int args); +int dooptcode(struct pike_string *name, + node *n, + struct pike_string *type, + int modifiers); INT32 get_opt_info(); /* Prototypes end here */ diff --git a/src/program.c b/src/program.c index a65b25795c67416067b01b0e720c6d511f8bba2c..aa7972a8f89979ad28fb75f2e9f1a718a2a57bf2 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.20 1997/02/11 07:20:15 hubbe Exp $"); +RCSID("$Id: program.c,v 1.21 1997/02/18 05:13:35 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -547,16 +547,14 @@ struct program *end_program() { union idptr tmp; struct pike_string *s; + push_locals(); s=make_shared_string("__INIT"); - tmp.offset=PC; - ins_byte(0, A_PROGRAM); /* num locals */ - ins_byte(0, A_PROGRAM); /* num args */ - dooptcode(s,mknode(F_ARG_LIST,init_node,mknode(F_RETURN,mkintnode(0),0)),0); - define_function(s, - function_type_string, - 0, /* ID_STATIC, */ - IDENTIFIER_PIKE_FUNCTION, - & tmp); + dooptcode(s, + mknode(F_ARG_LIST, + init_node,mknode(F_RETURN,mkintnode(0),0)), + function_type_string, + 0); + pop_locals(); free_string(s); init_node=0; } @@ -1664,3 +1662,29 @@ void count_memory_in_programs(INT32 *num_, INT32 *size_) *num_=num; *size_=size; } +void push_locals() +{ + struct locals *l; + l=ALLOC_STRUCT(locals); + l->current_type=0; + l->current_return_type=0; + l->next=local_variables; + l->current_number_of_locals=0; + l->max_number_of_locals=0; + local_variables=l; +} + +void pop_locals() +{ + struct locals *l; + free_all_local_names(); + l=local_variables->next; + if(local_variables->current_type) + free_string(local_variables->current_type); + if(local_variables->current_return_type) + free_string(local_variables->current_return_type); + free((char *)local_variables); + + local_variables=l; + /* insert check if ( local->next == parent locals ) here */ +} diff --git a/src/program.h b/src/program.h index 0a3ad12dc1f476ecc01c3d655605597efce5a668..326913e0413961ee39096aeac6a49af650f7ba43 100644 --- a/src/program.h +++ b/src/program.h @@ -249,6 +249,8 @@ void gc_check_all_programs(); void gc_mark_all_programs(); void gc_free_all_unreferenced_programs(); void count_memory_in_programs(INT32 *num_, INT32 *size_); +void push_locals(); +void pop_locals(); /* Prototypes end here */