From d2c608fc1d502911105fec8e5b5091a06a762031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Thu, 7 Nov 1996 20:57:40 -0800 Subject: [PATCH] object(foo), prog(), 'constant' and class foo {} implemented Rev: src/ChangeLog:1.18 Rev: src/builtin_functions.c:1.9 Rev: src/builtin_functions.h:1.2 Rev: src/docode.c:1.3 Rev: src/interpret.c:1.8 Rev: src/language.yacc:1.6 Rev: src/lex.c:1.6 Rev: src/object.c:1.3 Rev: src/object.h:1.3 Rev: src/pike_types.c:1.5 Rev: src/program.c:1.4 Rev: src/program.h:1.2 Rev: src/testsuite.in:1.6 --- src/ChangeLog | 8 +++ src/builtin_functions.c | 17 +---- src/builtin_functions.h | 1 - src/docode.c | 8 +-- src/interpret.c | 45 +++++------- src/language.yacc | 152 +++++++++++++++++++++++++++++++++------- src/lex.c | 1 + src/object.c | 74 +++++++++++-------- src/object.h | 3 + src/pike_types.c | 53 ++++++++++++-- src/program.c | 66 +++++++++++++++-- src/program.h | 8 +++ src/testsuite.in | 14 ++++ 13 files changed, 339 insertions(+), 111 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index d36296972d..499b87c9f6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +Thu Nov 7 20:49:42 1996 Fredrik Hubinette <hubbe@tymin.signum.se> + + * 'constant foo=<value>;' implemented on top level + * prog(); works now works like clone(prog) + * clone removed + * object(const) or object("prog") can now be used + * class foo {}; now works like constant foo = class {}; + Sat Nov 2 22:17:45 1996 Fredrik Hubinette <hubbe@tymin.blarg.com> * language.yacc: if(int a) implemente diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 0ab620cb11..6dc24feb91 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -262,21 +262,6 @@ void f_search(INT32 args) } } -void f_clone(INT32 args) -{ - struct object *o; - - if(args<1) - error("Too few arguments to clone.\n"); - - if(sp[-args].type != T_PROGRAM) - error("Bad argument 1 to clone.\n"); - - o=clone(sp[-args].u.program,args-1); - pop_stack(); - push_object(o); -} - void f_call_function(INT32 args) { INT32 expected_stack=sp-args+2-evaluator_stack; @@ -1454,7 +1439,7 @@ void init_builtin_efuns() add_efun("arrayp", f_arrayp, "function(mixed:int)",0); add_efun("backtrace",f_backtrace,"function(:array(array(function|int|string)))",OPT_EXTERNAL_DEPEND); add_efun("call_function",f_call_function,"function(mixed,mixed ...:mixed)",OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND); - add_efun("clone",f_clone,"function(program,mixed...:object)",OPT_EXTERNAL_DEPEND); + add_efun("column",f_column,"function(array,mixed:array)",0); add_efun("combine_path",f_combine_path,"function(string,string:string)",0); add_efun("compile_file",f_compile_file,"function(string:program)",OPT_EXTERNAL_DEPEND); diff --git a/src/builtin_functions.h b/src/builtin_functions.h index 5ef0f11cb0..d9ac9d8273 100644 --- a/src/builtin_functions.h +++ b/src/builtin_functions.h @@ -23,7 +23,6 @@ void f_random(INT32 args); void f_random_seed(INT32 args); void f_query_num_arg(INT32 args); void f_search(INT32 args); -void f_clone(INT32 args); void f_call_function(INT32 args); void f_backtrace(INT32 args); void f_add_constant(INT32 args); diff --git a/src/docode.c b/src/docode.c index cc83acaf0f..7e34f30292 100644 --- a/src/docode.c +++ b/src/docode.c @@ -424,9 +424,9 @@ static int do_docode2(node *n,int flags) break; case F_IDENTIFIER: - if(ID_FROM_INT(& fake_program, CDR(n)->u.number)->flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(& fake_program, CDR(n)->u.number)->flags)) { - yyerror("Cannot assign functions.\n"); + yyerror("Cannot assign functions or constants.\n"); }else{ if(do_docode(CAR(n),0)!=1) yyerror("RHS is void!"); emit(flags & DO_POP ? F_ASSIGN_GLOBAL_AND_POP:F_ASSIGN_GLOBAL, @@ -677,7 +677,7 @@ static int do_docode2(node *n,int flags) return 1; } else if(CAR(n)->token == F_IDENTIFIER && - ID_FROM_INT(& fake_program, CAR(n)->u.number)->flags & IDENTIFIER_FUNCTION) + IDENTIFIER_IS_FUNCTION(ID_FROM_INT(& fake_program, CAR(n)->u.number)->flags)) { emit2(F_MARK); do_docode(CDR(n),0); @@ -992,7 +992,7 @@ static int do_docode2(node *n,int flags) } case F_IDENTIFIER: - if(ID_FROM_INT(& fake_program, n->u.number)->flags & IDENTIFIER_FUNCTION) + if(IDENTIFIER_IS_FUNCTION(ID_FROM_INT(& fake_program, n->u.number)->flags)) { if(flags & DO_LVALUE) { diff --git a/src/interpret.c b/src/interpret.c index 9ab9009051..2e55742b20 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -568,32 +568,13 @@ static void eval_instruction(unsigned char *pc) break; /* The not so basic 'push value' instructions */ - CASE(F_GLOBAL) - { - struct identifier *i; - INT32 tmp=GET_ARG() + fp->context.identifier_level; - - if(!fp->current_object->prog) - error("Cannot access global variables in destructed object.\n"); - - i=ID_FROM_INT(fp->current_object->prog, tmp); - if(i->run_time_type == T_MIXED) - { - struct svalue *s; - s=(struct svalue *)GLOBAL_FROM_INT(tmp); - check_destructed(s); - assign_svalue_no_free(sp,s); - }else{ - union anything *u; - u=(union anything *)GLOBAL_FROM_INT(tmp); - check_short_destructed(u,i->run_time_type); - - assign_from_short_svalue_no_free(sp,u, i->run_time_type); - } - sp++; - print_return_value(); - break; - } + CASE(F_GLOBAL); + low_object_index_no_free(sp, + fp->current_object, + GET_ARG() + fp->context.identifier_level); + sp++; + print_return_value(); + break; CASE(F_LOCAL); assign_svalue_no_free(sp++,fp->locals+GET_ARG()); @@ -656,7 +637,6 @@ static void eval_instruction(unsigned char *pc) fp->locals[instr].u.integer--; break; - CASE(F_LTOSVAL); lvalue_to_svalue_no_free(sp,sp-2); sp++; @@ -692,6 +672,10 @@ static void eval_instruction(unsigned char *pc) error("Cannot access global variables in destructed object.\n"); i=ID_FROM_INT(fp->current_object->prog, tmp); + + if(!IDENTIFIER_IS_VARIABLE(i->flags)) + error("Cannot re-assign functions or constants.\n"); + if(i->run_time_type == T_MIXED) { sp[0].type=T_LVALUE; @@ -1461,6 +1445,13 @@ void strict_apply_svalue(struct svalue *s, INT32 args) apply_array(s->u.array,args); break; + case T_PROGRAM: + { + struct object *o=clone(s->u.program,args); + push_object(o); + } + break; + default: error("Call to non-function value.\n"); } diff --git a/src/language.yacc b/src/language.yacc index 5a1e2d157f..6098477d68 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -80,6 +80,7 @@ %token F_CLASS %token F_COLON_COLON %token F_COMMA +%token F_CONSTANT %token F_CONTINUE %token F_DEFAULT %token F_DIV_EQ @@ -299,6 +300,7 @@ void fix_comp_stack(int sp) %type <n> for_expr %type <n> foreach %type <n> gauge +%type <n> idents %type <n> lambda %type <n> local_name_list %type <n> lvalue @@ -341,13 +343,99 @@ string_constant: low_string optional_rename_inherit: ':' F_IDENTIFIER { $$=$2; } | { $$=0; } ; + +program_ref: string_constant + { + reference_shared_string($1); + push_string($1); + push_string($1); + reference_shared_string(current_file); + push_string(current_file); + SAFE_APPLY_MASTER("handle_inherit", 2); + + if(sp[-1].type != T_PROGRAM) + my_yyerror("Couldn't cast program to string (%s)",$1->str); + } + | idents + { + push_string(make_shared_string("")); + switch($1->token) + { + case F_CONSTANT: + if($1->u.sval.type == T_PROGRAM) + { + push_svalue(& $1->u.sval); + }else{ + yyerror("Illegal program identifier"); + push_int(0); + } + break; + + case F_IDENTIFIER: + { + struct identifier *i; + setup_fake_program(); + i=ID_FROM_INT(& fake_program, $1->u.number); + + if(IDENTIFIER_IS_CONSTANT(i->flags)) + { + push_svalue(PROG_FROM_INT(&fake_program, $1->u.number)->constants + + i->func.offset); + }else{ + yyerror("Illegal program identifier"); + push_int(0); + } + break; + } + } + free_node($1); + } + ; -inheritance: modifiers F_INHERIT string_constant optional_rename_inherit ';' +inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';' { - simple_do_inherit($3,$1,$4); + struct pike_string *s; + if(sp[-1].type == T_PROGRAM) + { + s=sp[-2].u.string; + if($4) s=$4; + do_inherit(sp[-1].u.program,$1,s); + if($4) free_string($4); + } + pop_n_elems(2); } ; +constant_name: F_IDENTIFIER '=' expr0 + { + int tmp; + /* This can be made more lenient in the future */ + if(!is_const($3)) + { + struct svalue tmp; + yyerror("Constant definition is not constant."); + tmp.type=T_INT; + tmp.u.integer=0; + add_constant($1,&tmp, current_modifiers); + } else { + tmp=eval_low($3); + if(tmp < 1) + yyerror("Error in constant definition."); + pop_n_elems(tmp-1); + add_constant($1,sp-1,current_modifiers); + free_string($1); + pop_stack(); + } + } + ; + +constant_list: constant_name + | constant_list ',' constant_name + ; + +constant: F_CONSTANT modifiers constant_list ';' + ; + block_or_semi: block { $$ = mknode(F_ARG_LIST,$1,mknode(F_RETURN,mkintnode(0),0)); @@ -458,6 +546,8 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' } | modifiers type_or_error name_list ';' {} | inheritance {} + | constant {} + | class {} | error { reset_type_stack(); @@ -471,7 +561,7 @@ optional_dot_dot_dot: F_DOT_DOT_DOT { $$=1; } ; optional_identifier: F_IDENTIFIER - | /* empty */ { $$=make_shared_string(""); } + | /* empty */ { $$=0; } ; @@ -484,6 +574,7 @@ new_arg_name: type optional_dot_dot_dot optional_identifier push_type(T_ARRAY); varargs=1; } + if(!$3) $3=make_shared_string(""); if(islocal($3) >= 0) my_yyerror("Variable '%s' appear twice in argument list.", $3->str); @@ -534,16 +625,25 @@ type2: type2 '|' type3 { push_type(T_OR); } type3: F_INT_ID { push_type(T_INT); } | F_FLOAT_ID { push_type(T_FLOAT); } | F_STRING_ID { push_type(T_STRING); } - | F_OBJECT_ID { push_type(T_OBJECT); } | F_PROGRAM_ID { push_type(T_PROGRAM); } | F_VOID_ID { push_type(T_VOID); } | F_MIXED_ID { push_type(T_MIXED); } + | F_OBJECT_ID opt_object_type { push_type(T_OBJECT); } | F_MAPPING_ID opt_mapping_type { push_type(T_MAPPING); } | F_ARRAY_ID opt_array_type { push_type(T_ARRAY); } | F_MULTISET_ID opt_array_type { push_type(T_MULTISET); } | F_FUNCTION_ID opt_function_type { push_type(T_FUNCTION); } ; +opt_object_type: /* Empty */ { push_type_int(0); } + | '(' program_ref ')' + { + if(sp[-1].type == T_PROGRAM) + push_type_int(sp[-1].u.program->id); + pop_n_elems(2); + } + ; + opt_function_type: '(' { type_stack_mark(); @@ -786,7 +886,7 @@ lambda: F_LAMBDA } ; -class: F_CLASS '{' +class: F_CLASS optional_identifier '{' { start_new_program(); } @@ -803,6 +903,7 @@ class: F_CLASS '{' s.type=T_PROGRAM; s.subtype=0; } + if($2) add_constant($2, &s, 0); $$=mksvaluenode(&s); free_svalue(&s); } @@ -1007,7 +1108,28 @@ expr4: string | sscanf | lambda | class - | F_IDENTIFIER + | idents + | expr4 '(' expr_list ')' { $$=mkapplynode($1,$3); } + | expr4 '[' expr0 ']' { $$=mknode(F_INDEX,$1,$3); } + | expr4 '[' comma_expr_or_zero F_DOT_DOT comma_expr_or_maxint ']' + { + $$=mknode(F_RANGE,$1,mknode(F_ARG_LIST,$3,$5)); + } + | '(' comma_expr2 ')' { $$=$2; } + | '(' '{' expr_list '}' ')' + { $$=mkefuncallnode("aggregate",$3); } + | '(' '[' m_expr_list ']' ')' + { $$=mkefuncallnode("aggregate_mapping",$3); }; + | F_MULTISET_START expr_list F_MULTISET_END + { $$=mkefuncallnode("aggregate_multiset",$2); } + | expr4 F_ARROW F_IDENTIFIER + { + $$=mknode(F_INDEX,$1,mkstrnode($3)); + free_string($3); + } + ; + +idents: F_IDENTIFIER { int i; struct efun *f; @@ -1037,24 +1159,6 @@ expr4: string } free_string($3); } - | expr4 '(' expr_list ')' { $$=mkapplynode($1,$3); } - | expr4 '[' expr0 ']' { $$=mknode(F_INDEX,$1,$3); } - | expr4 '[' comma_expr_or_zero F_DOT_DOT comma_expr_or_maxint ']' - { - $$=mknode(F_RANGE,$1,mknode(F_ARG_LIST,$3,$5)); - } - | '(' comma_expr2 ')' { $$=$2; } - | '(' '{' expr_list '}' ')' - { $$=mkefuncallnode("aggregate",$3); } - | '(' '[' m_expr_list ']' ')' - { $$=mkefuncallnode("aggregate_mapping",$3); }; - | F_MULTISET_START expr_list F_MULTISET_END - { $$=mkefuncallnode("aggregate_multiset",$2); } - | expr4 F_ARROW F_IDENTIFIER - { - $$=mknode(F_INDEX,$1,mkstrnode($3)); - free_string($3); - } | F_IDENTIFIER F_COLON_COLON F_IDENTIFIER { int f; diff --git a/src/lex.c b/src/lex.c index 6967475416..9e2116db0d 100644 --- a/src/lex.c +++ b/src/lex.c @@ -101,6 +101,7 @@ struct keyword reserved_words[] = { "catch", F_CATCH, }, { "class", F_CLASS, }, { "continue", F_CONTINUE, }, +{ "constant", F_CONSTANT, }, { "default", F_DEFAULT, }, { "do", F_DO, }, { "predef", F_PREDEF, }, diff --git a/src/object.c b/src/object.c index 7f39e727ca..8f4f163879 100644 --- a/src/object.c +++ b/src/object.c @@ -70,7 +70,7 @@ struct object *clone(struct program *p, int args) for(d=0;d<(int)frame.context.prog->num_identifiers;d++) { - if(frame.context.prog->identifiers[d].flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].flags)) continue; if(frame.context.prog->identifiers[d].run_time_type == T_MIXED) @@ -200,7 +200,7 @@ void destruct(struct object *o) for(d=0;d<(int)frame.context.prog->num_identifiers;d++) { - if(frame.context.prog->identifiers[d].flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].flags)) continue; if(frame.context.prog->identifiers[d].run_time_type == T_MIXED) @@ -298,35 +298,53 @@ void really_free_object(struct object *o) } -static void low_object_index_no_free(struct svalue *to, - struct object *o, - INT32 f) +void low_object_index_no_free(struct svalue *to, + struct object *o, + INT32 f) { struct identifier *i; struct program *p=o->prog; + + if(!p) + error("Cannot access global variables in destructed object.\n"); i=ID_FROM_INT(p, f); - if(i->flags & IDENTIFIER_FUNCTION) + switch(i->flags & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT)) { + case IDENTIFIER_FUNCTION: + case IDENTIFIER_C_FUNCTION: + case IDENTIFIER_PIKE_FUNCTION: to->type=T_FUNCTION; to->subtype=f; to->u.object=o; o->refs++; - } - else if(i->run_time_type == T_MIXED) - { - struct svalue *s; - s=(struct svalue *)LOW_GET_GLOBAL(o,f,i); - check_destructed(s); - assign_svalue_no_free(to, s); - } - else - { - union anything *u; - u=(union anything *)LOW_GET_GLOBAL(o,f,i); - check_short_destructed(u,i->run_time_type); - assign_from_short_svalue_no_free(to, u, i->run_time_type); + break; + + case IDENTIFIER_CONSTANT: + { + struct svalue *s; + s=PROG_FROM_INT(p,f)->constants + i->func.offset; + check_destructed(s); + assign_svalue_no_free(to, s); + break; + } + + case 0: + if(i->run_time_type == T_MIXED) + { + struct svalue *s; + s=(struct svalue *)LOW_GET_GLOBAL(o,f,i); + check_destructed(s); + assign_svalue_no_free(to, s); + } + else + { + union anything *u; + u=(union anything *)LOW_GET_GLOBAL(o,f,i); + check_short_destructed(u,i->run_time_type); + assign_from_short_svalue_no_free(to, u, i->run_time_type); + } } } @@ -399,9 +417,9 @@ static void object_low_set_index(struct object *o, i=ID_FROM_INT(p, f); - if(i->flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE(i->flags)) { - error("Cannot assign functions.\n"); + error("Cannot assign functions or constants.\n"); } else if(i->run_time_type == T_MIXED) { @@ -479,9 +497,9 @@ static union anything *object_low_get_item_ptr(struct object *o, i=ID_FROM_INT(p, f); - if(i->flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE(i->flags)) { - error("Cannot assign functions.\n"); + error("Cannot assign functions or constants.\n"); } else if(i->run_time_type == T_MIXED) { @@ -567,7 +585,7 @@ void verify_all_objects() { struct identifier *i; i=ID_FROM_INT(o->prog, e); - if(i->flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE(i->flags)) continue; if(i->run_time_type == T_MIXED) @@ -625,7 +643,7 @@ int object_equal_p(struct object *a, struct object *b, struct processing *p) { struct identifier *i; i=ID_FROM_INT(a->prog, e); - if(i->flags & IDENTIFIER_FUNCTION) + if(!IDENTIFIER_IS_VARIABLE(i->flags)) continue; if(i->run_time_type == T_MIXED) @@ -718,7 +736,7 @@ void gc_mark_object_as_referenced(struct object *o) i=ID_FROM_INT(o->prog, e); - if(i->flags & IDENTIFIER_FUNCTION) continue; + if(!IDENTIFIER_IS_VARIABLE(i->flags)) continue; if(i->run_time_type == T_MIXED) { @@ -747,7 +765,7 @@ void gc_check_all_objects() i=ID_FROM_INT(o->prog, e); - if(i->flags & IDENTIFIER_FUNCTION) continue; + if(!IDENTIFIER_IS_VARIABLE(i->flags)) continue; if(i->run_time_type == T_MIXED) { diff --git a/src/object.h b/src/object.h index 90d7d60a70..9abde9f91c 100644 --- a/src/object.h +++ b/src/object.h @@ -40,6 +40,9 @@ struct object *master(); void destruct(struct object *o); void destruct_objects_to_destruct(); void really_free_object(struct object *o); +void low_object_index_no_free(struct svalue *to, + struct object *o, + INT32 f); void object_index_no_free(struct svalue *to, struct object *o, struct svalue *index); diff --git a/src/pike_types.c b/src/pike_types.c index bbc4a74323..cbfcee4a0d 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -93,12 +93,16 @@ static int type_length(char *t) case T_INT: case T_FLOAT: case T_STRING: - case T_OBJECT: case T_PROGRAM: case T_MIXED: case T_VOID: case T_UNKNOWN: break; + + + case T_OBJECT: + t+=sizeof(INT32); + break; } return t-q; } @@ -161,6 +165,17 @@ void push_type(unsigned char tmp) yyerror("Type stack overflow."); } +void push_type_int(unsigned INT32 i) +{ + if(type_stackp + sizeof(i)> type_stack + sizeof(type_stack)) + yyerror("Type stack overflow."); + + type_stack_mark(); + MEMCPY(type_stackp, &i, sizeof(i)); + type_stackp+=sizeof(i); + type_stack_reverse(); +} + void push_unfinished_type(char *s) { int e; @@ -217,7 +232,11 @@ static void internal_parse_typeA(char **_s) if(!strcmp(buf,"int")) push_type(T_INT); else if(!strcmp(buf,"float")) push_type(T_FLOAT); - else if(!strcmp(buf,"object")) push_type(T_OBJECT); + else if(!strcmp(buf,"object")) + { + push_type_int(0); + push_type(T_OBJECT); + } else if(!strcmp(buf,"program")) push_type(T_PROGRAM); else if(!strcmp(buf,"string")) push_type(T_STRING); else if(!strcmp(buf,"void")) push_type(T_VOID); @@ -439,7 +458,10 @@ void stupid_describe_type(char *a,INT32 len) case T_FLOAT: printf("float"); break; case T_STRING: printf("string"); break; case T_PROGRAM: printf("program"); break; - case T_OBJECT: printf("object"); break; + case T_OBJECT: + printf("object(%ld)",(long)EXTRACT_INT(a+e+1)); + e+=sizeof(INT32); + break; case T_FUNCTION: printf("function"); break; case T_ARRAY: printf("array"); break; case T_MAPPING: printf("mapping"); break; @@ -475,7 +497,10 @@ char *low_describe_type(char *t) case T_INT: my_strcat("int"); break; case T_FLOAT: my_strcat("float"); break; case T_PROGRAM: my_strcat("program"); break; - case T_OBJECT: my_strcat("object"); break; + case T_OBJECT: + my_strcat("object"); + /* Prog id */ + break; case T_STRING: my_strcat("string"); break; case T_FUNCTION: @@ -654,6 +679,13 @@ static char *low_match_types(char *a,char *b, int flags) /* 'mixed' matches anything */ if(EXTRACT_UCHAR(a) == T_MIXED && !(flags & A_EXACT)) return a; if(EXTRACT_UCHAR(b) == T_MIXED && !(flags & B_EXACT)) return a; + + /* Special case (tm) */ + if(EXTRACT_UCHAR(a) == T_PROGRAM && EXTRACT_UCHAR(b)==T_FUNCTION) + { + return a; + } + if(EXTRACT_UCHAR(a) != EXTRACT_UCHAR(b)) return 0; ret=a; @@ -702,6 +734,13 @@ static char *low_match_types(char *a,char *b, int flags) if(!low_match_types(a+type_length(a),b+type_length(b),flags)) return 0; break; + case T_OBJECT: + a++; + b++; + if(!EXTRACT_INT(a) || !EXTRACT_INT(b)) break; + if(EXTRACT_INT(a) != EXTRACT_INT(b)) return 0; + break; + case T_MULTISET: case T_ARRAY: if(!low_match_types(++a,++b,flags)) return 0; @@ -709,7 +748,6 @@ static char *low_match_types(char *a,char *b, int flags) case T_INT: case T_FLOAT: case T_STRING: - case T_OBJECT: case T_PROGRAM: case T_VOID: case T_MIXED: @@ -802,6 +840,11 @@ static int low_get_return_type(char *a,char *b) push_unfinished_type(a); return 1; + case T_PROGRAM: + push_type_int(0); + push_type(T_OBJECT); + return 1; + default: push_type(T_MIXED); return 1; diff --git a/src/program.c b/src/program.c index b953546b4b..c46e051d6a 100644 --- a/src/program.c +++ b/src/program.c @@ -265,7 +265,7 @@ void check_program(struct program *p) fatal("Program ->prev == 0 but first_program != program.\n"); } - if(p->id > current_program_id || p->id < 0) + if(p->id > current_program_id || p->id <= 0) fatal("Program id is wrong.\n"); if(p->storage_needed < 0) @@ -329,7 +329,7 @@ void check_program(struct program *p) check_string(p->identifiers[e].name); check_string(p->identifiers[e].type); - if(p->identifiers[e].flags & ~7) + if(p->identifiers[e].flags & ~15) fatal("Unknown flags in identifier flag field.\n"); if(p->identifiers[e].run_time_type!=T_MIXED) @@ -672,9 +672,13 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) inherit.storage_offset += storage_offset; inherit.inherit_level ++; add_to_mem_block(A_INHERITS,(char *)&inherit,sizeof inherit); - + low_my_binary_strcat((char *)&name,sizeof(name),&inherit_names); - name=0; + if(name) + { + reference_shared_string(name); + name=0; + } } for (e=0; e < (int)p->num_identifier_references; e++) @@ -742,6 +746,7 @@ void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *na s=name; } do_inherit(sp[-1].u.program, flags, s); + free_string(s); pop_stack(); } @@ -828,6 +833,57 @@ int define_variable(struct pike_string *name, return n; } +int add_constant(struct pike_string *name, + struct svalue *c, + INT32 flags) +{ + int n; + +#ifdef DEBUG + if(name!=debug_findstring(name)) + fatal("define_variable on nonshared string.\n"); +#endif + + setup_fake_program(); + n = isidentifier(name); + + if(n != -1) + { + setup_fake_program(); + + if (IDENTIFIERP(n)->flags & ID_NOMASK) + my_yyerror("Illegal to redefine 'nomask' identifier \"%s\"", name->str); + + if(PROG_FROM_INT(& fake_program, n) == &fake_program) + my_yyerror("Identifier '%s' defined twice.",name->str); + } else { + struct identifier dummy; + struct reference ref; + + copy_shared_string(dummy.name, name); + dummy.type = get_type_of_svalue(c); + + dummy.flags = IDENTIFIER_CONSTANT; + dummy.run_time_type=c->type; + + dummy.func.offset=store_constant(c, 0); + + ref.flags=flags; + ref.identifier_offset=areas[A_IDENTIFIERS].s.len / sizeof dummy; + ref.inherit_offset=0; + + add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy); + fake_program.num_identifiers ++; + + n=areas[A_IDENTIFIER_REFERENCES].s.len / sizeof ref; + add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); + fake_program.num_identifier_references ++; + + } + + return n; +} + /* * define a new function * if func isn't given, it is supposed to be a prototype. @@ -1222,8 +1278,6 @@ struct program *compile_file(struct pike_string *file_name) if(fd < 0) error("Couldn't open file '%s'.\n",file_name->str); - - #define FILE_STATE #define PUSH #include "compilation.h" diff --git a/src/program.h b/src/program.h index 04de1ccc1b..268cad7a29 100644 --- a/src/program.h +++ b/src/program.h @@ -74,6 +74,11 @@ union idptr #define IDENTIFIER_C_FUNCTION 2 #define IDENTIFIER_FUNCTION 3 #define IDENTIFIER_VARARGS 4 +#define IDENTIFIER_CONSTANT 8 + +#define IDENTIFIER_IS_FUNCTION(X) ((X) & IDENTIFIER_FUNCTION) +#define IDENTIFIER_IS_CONSTANT(X) ((X) & IDENTIFIER_CONSTANT) +#define IDENTIFIER_IS_VARIABLE(X) (!((X) & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT))) struct identifier { @@ -185,6 +190,9 @@ int isidentifier(struct pike_string *s); int define_variable(struct pike_string *name, struct pike_string *type, INT32 flags); +int add_constant(struct pike_string *name, + struct svalue *c, + INT32 flags); INT32 define_function(struct pike_string *name, struct pike_string *type, INT16 flags, diff --git a/src/testsuite.in b/src/testsuite.in index a2e3410a33..004db5843a 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,3 +1,17 @@ +test_any([[object(File) o=File(); return objectp(o);]],1) +test_any([[object o=Regexp("foo"); return objectp(o);]],1) +test_any([[object o=Regexp("foo"); return object_program(o);]],Regexp) +test_any([[class Test {}; object(Test) o=Test(); return object_program(o);]],Test) +test_define_program(/test,[[constant foo = 1; int a() { return foo; }]]) +test_true(new("/test")->a()) +test_program(inherit "/test";) +test_program(inherit "/test"; int a() { return foo; } ) +test_define_program(/test,[[class TEST { int a() { return 1; } }]]) +test_program(inherit "/test"; inherit TEST; ) +test_compile_error(class { object(File) foo; object(Regexp) bar=foo; }) +test_do(class { object foo; object(Regexp) bar=foo; }) +test_do(class { object(File) foo; object bar=foo; }) + // ++ test_any([[int e; e++; return e;]],1) test_any([[int e; ++e; return e;]],1) -- GitLab