From 5b2674c2cd09b6e0e7dfdc86486486b489ce455e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Thu, 26 Jun 1997 23:55:22 -0700 Subject: [PATCH] variables in parents now works correctly Rev: lib/master.pike:1.43.2.3 Rev: lib/modules/Stack.pmod:1.2.2.1(DEAD) Rev: src/ChangeLog:1.97.2.3 Rev: src/builtin_functions.c:1.36.2.2 Rev: src/builtin_functions.h:1.3.2.2 Rev: src/cpp.h:1.1.2.1 Rev: src/docode.c:1.16.2.2 Rev: src/error.c:1.6.2.1 Rev: src/gc.c:1.8.2.1 Rev: src/interpret.c:1.42.2.2 Rev: src/language.yacc:1.42.2.3 Rev: src/las.c:1.32.2.2 Rev: src/las.h:1.6.2.2 Rev: src/lex.c:1.21.2.3 Rev: src/main.c:1.21.2.2 Rev: src/object.c:1.17.2.3 Rev: src/object.h:1.9.2.3 Rev: src/program.c:1.33.2.3 Rev: src/program.h:1.14.2.3 Rev: src/svalue.c:1.12.2.2 Rev: src/testsuite.in:1.40.2.3 --- lib/master.pike | 5 +- lib/modules/Stack.pmod | 47 ---------- src/ChangeLog | 4 + src/builtin_functions.c | 43 ++------- src/builtin_functions.h | 15 ++- src/cpp.h | 26 ++++++ src/docode.c | 22 ++++- src/error.c | 1 + src/gc.c | 21 +++-- src/interpret.c | 94 ++++++++++++++++++- src/language.yacc | 56 +++++------- src/las.c | 82 +++++++++++++---- src/las.h | 12 ++- src/lex.c | 5 +- src/main.c | 3 +- src/object.c | 197 +++++++++++++++++++++++----------------- src/object.h | 10 +- src/program.c | 141 ++++++++++++++++++++++++---- src/program.h | 25 ++++- src/svalue.c | 7 +- src/testsuite.in | 12 ++- 21 files changed, 553 insertions(+), 275 deletions(-) delete mode 100644 lib/modules/Stack.pmod create mode 100644 src/cpp.h diff --git a/lib/master.pike b/lib/master.pike index 25f788cb2d..4fad02869b 100644 --- a/lib/master.pike +++ b/lib/master.pike @@ -259,14 +259,13 @@ class dirnode void create(string name) { dirname=name; } object|program `[](string index) { - object m=((object)"/master"); - if(mixed o=m->findmodule(dirname+"/module")) + if(mixed o=findmodule(dirname+"/module")) { if(mixed tmp=o->_module_value) o=tmp; if(o=o[index]) return o; } index = dirname+"/"+index; - if(object o=((object)"/master")->findmodule(index)) + if(object o=findmodule(index)) { if(mixed tmp=o->_module_value) o=tmp; return o; diff --git a/lib/modules/Stack.pmod b/lib/modules/Stack.pmod deleted file mode 100644 index aeb471a65b..0000000000 --- a/lib/modules/Stack.pmod +++ /dev/null @@ -1,47 +0,0 @@ -#define error(X) throw( ({ (X), backtrace()[0..sizeof(backtrace())-2] }) ) - -class stack { - int ptr; - mixed *arr=allocate(32); - - void push(mixed val) - { - if(ptr==sizeof(arr)) arr+=allocate(ptr); - arr[ptr++]=val; - } - - mixed pop(void|int val) - { - mixed foo; - - if (val) { - if (ptr <= 0) { - error("Stack underflow\n"); - } - - if (ptr < val) { - val = ptr; - } - ptr -= val; - foo = arr[ptr..ptr + val - 1]; - - for (int i=0; i < val; i++) { - arr[ptr + i] = 0; /* Don't waste references */ - } - } else { - if(--ptr < 0) - error("Stack underflow\n"); - - foo=arr[ptr]; - arr[ptr]=0; /* Don't waste references */ - } - return foo; - } - - void reset() - { - arr=allocate(32); - ptr=0; - } -}; - diff --git a/src/ChangeLog b/src/ChangeLog index 702df0c80c..fb63905809 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +Thu Jun 26 20:45:53 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> + + * objects can now access variables in their parents + Wed Jun 25 15:33:23 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> * Compiler is now two-pass -> no more prototypes diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 2b0ce84c7c..3e5dc1ccc3 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.36.2.1 1997/06/25 22:46:35 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.36.2.2 1997/06/27 06:55:13 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -281,28 +281,6 @@ void f_call_function(INT32 args) } } -void f_parent(INT32 args) -{ - struct object *o; - if(!args) - { - o=fp->current_object; - }else{ - if(sp[-args].type!=T_OBJECT) - error("Bad argument 1 to parent()\n"); - o=sp[-args].u.object; - } - o->refs++; - pop_n_elems(args); - if(o->parent) - { - ref_push_object(o->parent); - }else{ - push_int(0); - } - free_object(o); -} - void f_backtrace(INT32 args) { INT32 frames; @@ -858,16 +836,14 @@ void f_object_program(INT32 args) { if(o->parent && o->parent->prog) { - INT32 i=find_child(o->parent->prog, p); - if(i!=-1) - { - o->refs++; - pop_n_elems(args); - push_object(o->parent); - sp[-1].subtype=i; - sp[-1].type=T_FUNCTION; - return; - } + INT32 id=o->parent_identifier; + o=o->parent; + o->refs++; + pop_n_elems(args); + push_object(o); + sp[-1].subtype=id; + sp[-1].type=T_FUNCTION; + return; }else{ p->refs++; pop_n_elems(args); @@ -1804,6 +1780,5 @@ void init_builtin_efuns() add_efun("encode_value", f_encode_value, "function(mixed:string)", OPT_TRY_OPTIMIZE); add_efun("decode_value", f_decode_value, "function(string:mixed)", OPT_TRY_OPTIMIZE); - add_efun("parent", f_parent, "function(object|void:object)", OPT_EXTERNAL_DEPEND); } diff --git a/src/builtin_functions.h b/src/builtin_functions.h index 83f9da8866..704a49da59 100644 --- a/src/builtin_functions.h +++ b/src/builtin_functions.h @@ -26,7 +26,6 @@ void f_search(INT32 args); void f_call_function(INT32 args); void f_backtrace(INT32 args); void f_add_constant(INT32 args); -void f_compile_file(INT32 args); void f_combine_path(INT32 args); void f_function_object(INT32 args); void f_function_name(INT32 args); @@ -40,7 +39,6 @@ struct callback *add_exit_callback(callback_func call, void *arg, callback_func free_func); void f_exit(INT32 args); -void f_query_host_name(INT32 args); void f_time(INT32 args); void f_crypt(INT32 args); void f_destruct(INT32 args); @@ -51,7 +49,7 @@ void f_object_program(INT32 args); void f_reverse(INT32 args); struct tupel; void f_replace(INT32 args); -void f_compile_string(INT32 args); +void f_compile(INT32 args); void f_mkmapping(INT32 args); void f_objectp(INT32 args); void f_functionp(INT32 args); @@ -63,6 +61,7 @@ TYPEP(f_arrayp, "arrayp", T_ARRAY) TYPEP(f_multisetp, "multisetp", T_MULTISET) TYPEP(f_stringp, "stringp", T_STRING) TYPEP(f_floatp, "floatp", T_FLOAT) +void f_programp(INT32 args); void f_sort(INT32 args); void f_rows(INT32 args); void f_column(INT32 args); @@ -70,9 +69,15 @@ void f__verify_internals(INT32 args); void f_localtime(INT32 args); void f_glob(INT32 args); struct callback *add_memory_usage_callback(callback_func call, - void *arg, - callback_func free_func); + void *arg, + callback_func free_func); void f__memory_usage(INT32 args); +void f__next(INT32 args); +void f__prev(INT32 args); +void f__refs(INT32 args); +void f_replace_master(INT32 args); +void f_gethrvtime(INT32 args); +void f_gethrtime(INT32 args); void init_builtin_efuns(); /* Prototypes end here */ diff --git a/src/cpp.h b/src/cpp.h new file mode 100644 index 0000000000..7fcca20dba --- /dev/null +++ b/src/cpp.h @@ -0,0 +1,26 @@ +#ifndef CPP_H +#define CPP_H + +#ifndef STRUCT_HASH_ENTRY_DECLARED +struct hash_entry; +#define STRUCT_HASH_ENTRY_DECLARED +#endif + +/* Prototypes begin here */ +struct pike_predef_s; +struct define_part; +struct define_argument; +struct define; +struct cpp; +void cpp_error(struct cpp *this,char *err); +void PUSH_STRING(char *str, + INT32 len, + dynamic_buffer *buf); +void free_one_define(struct hash_entry *h); +void f_cpp(INT32 args); +void init_cpp(); +void add_predefine(char *s); +void exit_cpp(); +/* Prototypes end here */ + +#endif diff --git a/src/docode.c b/src/docode.c index 2d1d1b3524..80d8baa7ba 100644 --- a/src/docode.c +++ b/src/docode.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: docode.c,v 1.16.2.1 1997/06/25 22:46:36 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.16.2.2 1997/06/27 06:55:15 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.h" @@ -255,12 +255,25 @@ static int do_docode2(node *n,int flags) case F_INDEX: case F_ARROW: case F_ARG_LIST: + case F_EXTERNAL: break; } } switch(n->token) { + case F_EXTERNAL: + emit(F_LDA, n->u.integer.a); + if(flags & DO_LVALUE) + { + emit(F_EXTERNAL_LVALUE, n->u.integer.b); + return 2; + }else{ + emit(F_EXTERNAL, n->u.integer.b); + return 1; + } + break; + case F_UNDEFINED: yyerror("Undefined identifier"); emit(F_NUMBER,0); @@ -693,14 +706,15 @@ static int do_docode2(node *n,int flags) tmp=findstring("call_function"); if(!tmp) yyerror("No call_function efun."); - if(!find_module_identifier(tmp)) + foo=find_module_identifier(tmp); + if(!foo || !foo->token==F_CONSTANT) { yyerror("No call_function efun."); }else{ - tmp1=store_constant(sp-1, 1); - pop_stack(); + tmp1=store_constant(& foo->u.sval, 1); emit(F_APPLY, tmp1); } + free_node(foo); return 1; } diff --git a/src/error.c b/src/error.c index 1e0c968a68..c029503f7d 100644 --- a/src/error.c +++ b/src/error.c @@ -46,6 +46,7 @@ void throw() ATTRIBUTE((noreturn)) #endif free_object(fp->current_object); free_program(fp->context.prog); + if(fp->context.parent) free_object(fp->context.parent); fp = fp->parent_frame; } diff --git a/src/gc.c b/src/gc.c index a3d1f008be..80f8fd6f42 100644 --- a/src/gc.c +++ b/src/gc.c @@ -108,7 +108,7 @@ static struct marker *getmark(void *a) } #ifdef DEBUG -static void *check_for =0; +void *gc_check_for =0; static void gdb_gc_stop_here(void *a) { @@ -119,13 +119,14 @@ static void gdb_gc_stop_here(void *a) INT32 gc_check(void *a) { #ifdef DEBUG - if(check_for) + if(gc_check_for) { - if(check_for == a) + if(gc_check_for == a) { gdb_gc_stop_here(a); + return -2; } - return 0; + return -1; } #endif return getmark(a)->refs++; @@ -138,16 +139,24 @@ int gc_is_referenced(void *a) #ifdef DEBUG if(m->refs > *(INT32 *)a) { - check_for=a; + gc_check_for=a; + + fprintf(stderr,"Too many ref counts found %d > %d (%lx)\n",m->refs, *(INT32 *)a, (long)a); + fprintf(stderr,"Checking arrays\n"); gc_check_all_arrays(); + fprintf(stderr,"Checking multisets\n"); gc_check_all_multisets(); + fprintf(stderr,"Checking mappings\n"); gc_check_all_mappings(); + fprintf(stderr,"Checking programs\n"); gc_check_all_programs(); + fprintf(stderr,"Checking objects\n"); gc_check_all_objects(); + fprintf(stderr,"Checking callbacks\n"); call_callback(& gc_callbacks, (void *)0); - check_for=0; + gc_check_for=0; fatal("Ref counts are totally wrong!!!\n"); } #endif diff --git a/src/interpret.c b/src/interpret.c index 28b4730238..9830859669 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.42.2.1 1997/06/25 22:46:37 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.42.2.2 1997/06/27 06:55:16 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -479,7 +479,7 @@ static int o_catch(unsigned char *pc); static void eval_instruction(unsigned char *pc) { - unsigned INT32 instr, prefix=0; + unsigned INT32 accumulator=0, instr, prefix=0; while(1) { fp->pc = pc; @@ -560,6 +560,9 @@ static void eval_instruction(unsigned char *pc) CASE(F_PREFIX_CHARX256); prefix+=EXTRACT_UCHAR(pc++)<<8; break; + + CASE(F_LDA); accumulator=GET_ARG(); break; + /* Push number */ CASE(F_CONST0); push_int(0); break; CASE(F_CONST1); push_int(1); break; @@ -568,6 +571,7 @@ static void eval_instruction(unsigned char *pc) CASE(F_NUMBER); push_int(GET_ARG()); break; CASE(F_NEG_NUMBER); push_int(-GET_ARG()); break; + /* The rest of the basic 'push value' instructions */ CASE(F_STRING); copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]); @@ -614,6 +618,82 @@ static void eval_instruction(unsigned char *pc) print_return_value(); break; + CASE(F_EXTERNAL); + { + struct inherit *inherit; + struct program *p; + INT32 id=GET_ARG(); + struct object *o=fp->context.parent; + INT32 i=fp->context.parent_identifier; + + while(1) + { + if(!o) + error("Parent no longer exists\n"); + + if(!(p=o->prog)) + error("Attempting to access variable in destructed object\n"); + + inherit=INHERIT_FROM_INT(p, i); + + if(!accumulator) break; + --accumulator; + + if(p->identifier_references[id].inherit_offset==0) + { + i=o->parent_identifier; + o=o->parent; + }else{ + i=inherit->parent_identifier; + o=inherit->parent; + } + } + + low_object_index_no_free(sp, + o, + id + inherit->identifier_level); + sp++; + print_return_value(); + break; + } + + CASE(F_EXTERNAL_LVALUE); + { + struct inherit *inherit; + struct program *p; + INT32 id=GET_ARG(); + struct object *o=fp->context.parent; + INT32 i=fp->context.parent_identifier; + + while(1) + { + if(!o) + error("Parent no longer exists\n"); + + if(!(p=o->prog)) + error("Attempting to access variable in destructed object\n"); + + inherit=INHERIT_FROM_INT(p, i); + + if(!accumulator) break; + accumulator--; + + if(p->identifier_references[id].inherit_offset==0) + { + i=o->parent_identifier; + o=o->parent; + }else{ + i=inherit->parent_identifier; + o=inherit->parent; + } + } + + ref_push_object(o); + sp->type=T_LVALUE; + sp->u.integer=id + inherit->identifier_level; + sp++; + break; + } CASE(F_MARK_AND_LOCAL); *(mark_sp++)=sp; CASE(F_LOCAL); @@ -1214,6 +1294,7 @@ int apply_low_safe_and_stupid(struct object *o, INT32 offset) new_frame.fun = -1; new_frame.pc = 0; new_frame.current_storage=o->storage; + new_frame.context.parent=0; fp = & new_frame; new_frame.current_object->refs++; @@ -1279,6 +1360,8 @@ void apply_low(struct object *o, int fun, int args) new_frame.parent_frame = fp; new_frame.current_object = o; new_frame.context = p->inherits[ ref->inherit_offset ]; + if(!ref->inherit_offset) new_frame.context.parent=o->parent; + function = new_frame.context.prog->identifiers + ref->identifier_offset; new_frame.locals = sp - args; @@ -1289,6 +1372,7 @@ void apply_low(struct object *o, int fun, int args) new_frame.current_object->refs++; new_frame.context.prog->refs++; + if(new_frame.context.parent) new_frame.context.parent->refs++; #ifdef DEBUG if(t_flag) @@ -1354,7 +1438,10 @@ void apply_low(struct object *o, int fun, int args) struct svalue *s=fp->context.prog->constants+function->func.offset; if(s->type == T_PROGRAM) { - struct object *tmp=parent_clone_object(s->u.program,o,args); + struct object *tmp=parent_clone_object(s->u.program, + o, + fun, + args); push_object(tmp); }else{ error("Calling strange value!\n"); @@ -1424,6 +1511,7 @@ void apply_low(struct object *o, int fun, int args) sp++; } + if(new_frame.context.parent) free_object(new_frame.context.parent); free_object(new_frame.current_object); free_program(new_frame.context.prog); diff --git a/src/language.yacc b/src/language.yacc index 7c194632eb..505f33d4db 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -11,7 +11,7 @@ */ %token F_PREFIX_256 F_PREFIX_512 F_PREFIX_768 F_PREFIX_1024 %token F_PREFIX_CHARX256 F_PREFIX_WORDX256 F_PREFIX_24BITX256 -%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 +%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 F_LDA %token F_CALL_LFUN F_CALL_LFUN_AND_POP %token F_APPLY F_APPLY_AND_POP F_MARK_APPLY F_MARK_APPLY_POP @@ -31,8 +31,10 @@ /* * Basic value pushing */ -%token F_LFUN F_GLOBAL F_LOCAL F_2_LOCALS F_MARK_AND_LOCAL -%token F_GLOBAL_LVALUE F_LOCAL_LVALUE +%token F_LFUN +%token F_GLOBAL F_GLOBAL_LVALUE +%token F_LOCAL F_2_LOCALS F_LOCAL_LVALUE F_MARK_AND_LOCAL +%token F_EXTERNAL F_EXTERNAL_LVALUE %token F_CLEAR_LOCAL F_CLEAR_2_LOCAL F_CLEAR_STRING_SUBTYPE %token F_CONSTANT F_FLOAT F_STRING F_ARROW_STRING %token F_NUMBER F_NEG_NUMBER F_CONST_1 F_CONST0 F_CONST1 F_BIGNUM @@ -157,7 +159,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.42.2.2 1997/06/25 22:46:38 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.42.2.3 1997/06/27 06:55:17 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -390,16 +392,8 @@ program_ref: string_constant break; case T_FUNCTION: - { - struct program *p=program_from_function(sp-1); - if(p) - { - p->refs++; - pop_stack(); - push_program(p); + if(program_from_function(sp-1)) break; - } - } default: yyerror("Illegal program identifier"); @@ -416,12 +410,11 @@ program_ref: string_constant inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';' { - if(sp[-1].type == T_PROGRAM && - !(new_program->flags & PROGRAM_PASS_1_DONE)) + if(!(new_program->flags & PROGRAM_PASS_1_DONE)) { struct pike_string *s=sp[-2].u.string; if($4) s=$4; - do_inherit(sp[-1].u.program,$1,s); + do_inherit(sp-1,$1,s); } if($4) free_string($4); pop_n_elems(2); @@ -679,9 +672,10 @@ type3: F_INT_ID { push_type(T_INT); } opt_object_type: /* Empty */ { push_type_int(0); } | '(' program_ref ')' { - if(sp[-1].type == T_PROGRAM) + struct program *p=program_from_svalue(sp-1); + if(p) { - push_type_int(sp[-1].u.program->id); + push_type_int(p->id); }else{ yyerror("Not a valid program specifier"); push_type_int(0); @@ -960,25 +954,20 @@ class: modifiers F_CLASS F_IDENTIFIER } failsafe_program { - struct svalue s; + struct program *p; if(compiler_pass == 1) - s.u.program=end_first_pass(0); + p=end_first_pass(0); else - s.u.program=end_program(); + p=end_program(); - if(!s.u.program) - { + $$=mkidentifiernode(isidentifier($3)); + + if(!p) yyerror("Class definition failed."); - s.type=T_INT; - s.subtype=0; - } else { - s.type=T_PROGRAM; - s.subtype=0; - } + else + free_program(p); free_string($3); - $$=mksvaluenode(&s); - free_svalue(&s); } ; @@ -1249,10 +1238,7 @@ low_idents: F_IDENTIFIER $$=mklocalnode(i); }else if((i=isidentifier($1))>=0){ $$=mkidentifiernode(i); - }else if(find_module_identifier($1)){ - $$=mkconstantsvaluenode(sp-1); - pop_stack(); - }else{ + }else if(!($$=find_module_identifier($1))){ $$=0; if( get_master() && !num_parse_error) { diff --git a/src/las.c b/src/las.c index abf41900f6..8c26260334 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.32.2.1 1997/06/25 22:46:39 hubbe Exp $"); +RCSID("$Id: las.c,v 1.32.2.2 1997/06/27 06:55:17 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -45,6 +45,7 @@ int car_is_node(node *n) { switch(n->token) { + case F_EXTERNAL: case F_IDENTIFIER: case F_CONSTANT: case F_LOCAL: @@ -59,6 +60,7 @@ int cdr_is_node(node *n) { switch(n->token) { + case F_EXTERNAL: case F_IDENTIFIER: case F_CONSTANT: case F_LOCAL: @@ -377,13 +379,12 @@ node *mkefuncallnode(char *function, node *args) struct pike_string *name; node *n; name = findstring(function); - if(!name || !find_module_identifier(name)) + if(!name || !(n=find_module_identifier(name))) { my_yyerror("Internally used efun undefined: %s",function); return mkintnode(0); } - n=mkapplynode(mksvaluenode(sp-1), args); - pop_stack(); + n=mkapplynode(n, args); return n; } @@ -431,6 +432,27 @@ node *mkidentifiernode(int i) return res; } +node *mkexternalnode(int level, + int i, + struct identifier *id) +{ + node *res = mkemptynode(); + res->token = F_EXTERNAL; + + copy_shared_string(res->type, id->type); + + /* FIXME */ + res->node_info = OPT_NOT_CONST; + res->tree_info=res->node_info; + +#ifdef __CHECKER__ + CDR(res)=0; +#endif + res->u.integer.a = level; + res->u.integer.b = i; + return res; +} + node *mkcastnode(struct pike_string *type,node *n) { node *res; @@ -455,6 +477,9 @@ node *mkcastnode(struct pike_string *type,node *n) void resolv_constant(node *n) { struct identifier *i; + struct program *p; + INT32 numid; + if(!n) { push_int(0); @@ -463,30 +488,49 @@ void resolv_constant(node *n) { case F_CONSTANT: push_svalue(& n->u.sval); - break; + return; - case F_IDENTIFIER: - i=ID_FROM_INT(new_program, n->u.number); - - if(IDENTIFIER_IS_CONSTANT(i->flags)) + case F_EXTERNAL: + p=parent_compilation(n->u.integer.a); + if(!p) { - push_svalue(PROG_FROM_INT(new_program, n->u.number)->constants + - i->func.offset); - }else{ - yyerror("Identifier is not a constant"); + yyerror("Failed to resolv external constant"); push_int(0); + return; } + numid=n->u.integer.b; + break; + + case F_IDENTIFIER: + p=new_program; + numid=n->u.number; break; case F_LOCAL: - yyerror("Expected constant, got local variable"); - push_int(0); - break; + yyerror("Expected constant, got local variable"); + push_int(0); + return; case F_GLOBAL: - yyerror("Expected constant, got global variable"); - push_int(0); - break; + yyerror("Expected constant, got global variable"); + push_int(0); + return; + + default: + yyerror("Expected constant, got something else"); + push_int(0); + return; + } + + i=ID_FROM_INT(p, numid); + + if(IDENTIFIER_IS_CONSTANT(i->flags)) + { + push_svalue(PROG_FROM_INT(new_program, numid)->constants + + i->func.offset); + }else{ + yyerror("Identifier is not a constant"); + push_int(0); } } } diff --git a/src/las.h b/src/las.h index 7b750e149a..e3b1ad1c28 100644 --- a/src/las.h +++ b/src/las.h @@ -35,9 +35,17 @@ struct node_s { struct node_s *a,*b; } node; + struct + { + int a,b; + } integer; } u; }; +#ifndef STRUCT_NODE_S_DECLARED +#define STRUCT_NODE_S_DECLARED +#endif + typedef struct node_s node; extern node *init_node; @@ -93,6 +101,9 @@ node *mkefuncallnode(char *function, node *args); node *mkopernode(char *oper_id, node *arg1, node *arg2); node *mklocalnode(int var); node *mkidentifiernode(int i); +node *mkexternalnode(int level, + int i, + struct identifier *id); node *mkcastnode(struct pike_string *type,node *n); void resolv_constant(node *n); node *index_node(node *n, struct pike_string * id); @@ -116,7 +127,6 @@ int dooptcode(struct pike_string *name, node *n, struct pike_string *type, int modifiers); -INT32 get_opt_info(); /* Prototypes end here */ #define CAR(n) ((n)->u.node.a) diff --git a/src/lex.c b/src/lex.c index 507d5e682c..fb4c3e8170 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.21.2.2 1997/06/25 22:46:39 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.21.2.3 1997/06/27 06:55:18 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -141,6 +141,9 @@ struct keyword instr_names[]= { "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG }, { "local function", F_LFUN, I_HASARG }, { "local", F_LOCAL, I_HASARG }, +{ "external", F_EXTERNAL, I_HASARG }, +{ "& external", F_EXTERNAL_LVALUE, I_HASARG }, +{ "LDA", F_LDA, I_HASARG }, { "mark & local", F_MARK_AND_LOCAL, I_HASARG }, { "ltosval2", F_LTOSVAL2 }, { "lvalue to svalue", F_LTOSVAL }, diff --git a/src/main.c b/src/main.c index 15b253193a..ac212dc6b0 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: main.c,v 1.21.2.1 1997/06/25 22:46:40 hubbe Exp $"); +RCSID("$Id: main.c,v 1.21.2.2 1997/06/27 06:55:19 hubbe Exp $"); #include "types.h" #include "backend.h" #include "module.h" @@ -23,6 +23,7 @@ RCSID("$Id: main.c,v 1.21.2.1 1997/06/25 22:46:40 hubbe Exp $"); #include "dynamic_load.h" #include "gc.h" #include "mapping.h" +#include "cpp.h" #ifdef HAVE_LOCALE_H #include <locale.h> diff --git a/src/object.c b/src/object.c index 5b9aa08600..e23b890d09 100644 --- a/src/object.c +++ b/src/object.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: object.c,v 1.17.2.2 1997/06/25 22:46:41 hubbe Exp $"); +RCSID("$Id: object.c,v 1.17.2.3 1997/06/27 06:55:19 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -19,6 +19,8 @@ RCSID("$Id: object.c,v 1.17.2.2 1997/06/25 22:46:41 hubbe Exp $"); #include "gc.h" #include "backend.h" #include "callback.h" +#include "cpp.h" +#include "builtin_functions.h" struct object *master_object = 0; struct program *master_program =0; @@ -33,13 +35,9 @@ void setup_fake_object() fake_object.refs=0xffffff; } -struct object *low_clone(struct program *p, - struct object *parent) +static struct object *low_clone(struct program *p) { - int e; struct object *o; - struct frame frame; - if(!(p->flags & PROGRAM_FINISHED)) error("Attempting to clone an unfinished program\n"); @@ -48,14 +46,23 @@ struct object *low_clone(struct program *p, o=(struct object *)xalloc(sizeof(struct object)-1+p->storage_needed); o->prog=p; - if((o->parent=parent)) parent->refs++; p->refs++; o->next=first_object; o->prev=0; + o->parent=0; + o->parent_identifier=0; if(first_object) first_object->prev=o; first_object=o; o->refs=1; + return o; +} + +static void call_c_initializers(struct object *o) +{ + int e; + struct frame frame; + struct program *p=o->prog; frame.parent_frame=fp; frame.current_object=o; @@ -104,11 +111,9 @@ struct object *low_clone(struct program *p, free_object(frame.current_object); fp = frame.parent_frame; - - return o; } -static void init_object(struct object *o, int args) +static void call_pike_initializers(struct object *o, int args) { apply_lfun(o,LFUN___INIT,0); pop_stack(); @@ -118,17 +123,23 @@ static void init_object(struct object *o, int args) struct object *clone_object(struct program *p, int args) { - struct object *o=low_clone(p,0); - init_object(o,args); + struct object *o=low_clone(p); + call_c_initializers(o); + call_pike_initializers(o,args); return o; } struct object *parent_clone_object(struct program *p, struct object *parent, + int parent_identifier, int args) { - struct object *o=low_clone(p,parent); - init_object(o,args); + struct object *o=low_clone(p); + o->parent=parent; + parent->refs++; + o->parent_identifier=parent_identifier; + call_c_initializers(o); + call_pike_initializers(o,args); return o; } @@ -177,9 +188,10 @@ struct object *get_master() master_program=sp[-1].u.program; sp--; } - master_object=low_clone(master_program,0); + master_object=low_clone(master_program); - init_object(master_object,0); + call_c_initializers(master_object); + call_pike_initializers(master_object,0); inside = 0; return master_object; @@ -405,32 +417,6 @@ void low_object_index_no_free(struct svalue *to, } } -void object_index_no_free2(struct svalue *to, - struct object *o, - struct svalue *index) -{ - struct program *p; - int f; - - if(!o || !(p=o->prog)) - { - error("Lookup in destructed object.\n"); - return; /* make gcc happy */ - } - - if(index->type != T_STRING) - error("Lookup on non-string value.\n"); - - f=find_shared_string_identifier(index->u.string, p); - if(f < 0) - { - to->type=T_INT; - to->subtype=NUMBER_UNDEFINED; - to->u.integer=0; - }else{ - low_object_index_no_free(to, o, f); - } -} #define ARROW_INDEX_P(X) ((X)->type==T_STRING && (X)->subtype) @@ -439,23 +425,46 @@ void object_index_no_free(struct svalue *to, struct svalue *index) { struct program *p; - int lfun; + int f; if(!o || !(p=o->prog)) { error("Lookup in destructed object.\n"); return; /* make gcc happy */ } - lfun=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX; - - if(p->lfuns[lfun] != -1) + f=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX; + if(p->lfuns[f] != -1) { push_svalue(index); - apply_lfun(o,lfun,1); + apply_lfun(o,f,1); to=sp; sp--; - } else { - object_index_no_free2(to,o,index); + return; + } + switch(index->type) + { + case T_STRING: + f=find_shared_string_identifier(index->u.string, p); + free_string(index->u.string); + index->type=T_LVALUE; + index->u.integer=f; + break; + + case T_LVALUE: + f=index->u.integer; + break; + + default: + error("Lookup on non-string value.\n"); + } + + if(f < 0) + { + to->type=T_INT; + to->subtype=NUMBER_UNDEFINED; + to->u.integer=0; + }else{ + low_object_index_no_free(to, o, f); } } @@ -494,9 +503,9 @@ void object_low_set_index(struct object *o, } } -void object_set_index2(struct object *o, - struct svalue *index, - struct svalue *from) +void object_set_index(struct object *o, + struct svalue *index, + struct svalue *from) { struct program *p; int f; @@ -506,42 +515,39 @@ void object_set_index2(struct object *o, error("Lookup in destructed object.\n"); return; /* make gcc happy */ } - - if(index->type != T_STRING) - error("Lookup on non-string value.\n"); - - f=find_shared_string_identifier(index->u.string, p); - if(f < 0) + f=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX; + if(p->lfuns[f] != -1) { - error("No such variable (%s) in object.\n", index->u.string->str); - }else{ - object_low_set_index(o, f, from); + push_svalue(index); + push_svalue(from); + apply_lfun(o,f,2); + pop_stack(); + return; } -} + switch(index->type) + { + case T_STRING: + f=find_shared_string_identifier(index->u.string, p); + if(f<0) + error("No such variable (%s) in object.\n", index->u.string->str); + free_string(index->u.string); + index->type=T_LVALUE; + index->u.integer=f; + break; -void object_set_index(struct object *o, - struct svalue *index, - struct svalue *from) -{ - struct program *p; - int lfun; + case T_LVALUE: + f=index->u.integer; + break; - if(!o || !(p=o->prog)) - { - error("Lookup in destructed object.\n"); - return; /* make gcc happy */ + default: + error("Lookup on non-string value.\n"); } - lfun=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX; - - if(p->lfuns[lfun] != -1) + if(f < 0) { - push_svalue(index); - push_svalue(from); - apply_lfun(o,lfun,2); - pop_stack(); - } else { - object_set_index2(o,index,from); + error("Assigning nonexistant variable in object\n"); + }else{ + object_low_set_index(o, f, from); } } @@ -596,10 +602,24 @@ union anything *object_get_item_ptr(struct object *o, if(p->lfuns[f] != -1) error("Cannot do incremental operations on overloaded index (yet).\n"); - if(index->type != T_STRING) + switch(index->type) + { + case T_STRING: + f=find_shared_string_identifier(index->u.string, p); + free_string(index->u.string); + index->type=T_LVALUE; + index->u.integer=f; + break; + + case T_LVALUE: + f=index->u.integer; + break; + + default: error("Lookup on non-string value.\n"); + return 0; + } - f=find_shared_string_identifier(index->u.string, p); if(f < 0) { error("No such variable in object.\n"); @@ -810,6 +830,9 @@ void gc_mark_object_as_referenced(struct object *o) { if(gc_mark(o)) { + if(o->parent) + gc_mark_object_as_referenced(o); + if(o->prog) { INT32 e; @@ -839,6 +862,14 @@ void gc_check_all_objects() struct object *o; for(o=first_object;o;o=o->next) { +#ifdef DEBUG + if(o->parent) + if(gc_check(o->parent)==-2) + fprintf(stderr,"(in object at %lx -> parent)\n",(long)o); +#else + if(o->parent) + gc_check(o->parent); +#endif if(o->prog) { INT32 e; diff --git a/src/object.h b/src/object.h index 4d39c455fd..e62666dbf3 100644 --- a/src/object.h +++ b/src/object.h @@ -19,6 +19,7 @@ struct object INT32 refs; /* Reference count, must be first. */ struct program *prog; struct object *parent; + INT16 parent_identifier; struct object *next; struct object *prev; char storage[1]; @@ -39,11 +40,10 @@ extern struct program *master_program; /* Prototypes begin here */ void setup_fake_object(); -struct object *low_clone(struct program *p, - struct object *parent); struct object *clone_object(struct program *p, int args); struct object *parent_clone_object(struct program *p, struct object *parent, + int parent_identifier, int args); struct object *get_master(); struct object *master(); @@ -53,18 +53,12 @@ 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_free2(struct svalue *to, - struct object *o, - struct svalue *index); void object_index_no_free(struct svalue *to, struct object *o, struct svalue *index); void object_low_set_index(struct object *o, int f, struct svalue *from); -void object_set_index2(struct object *o, - struct svalue *index, - struct svalue *from); void object_set_index(struct object *o, struct svalue *index, struct svalue *from); diff --git a/src/program.c b/src/program.c index a23b69b922..4f44ed04fd 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.33.2.2 1997/06/25 22:46:43 hubbe Exp $"); +RCSID("$Id: program.c,v 1.33.2.3 1997/06/27 06:55:20 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -147,12 +147,16 @@ void use_module(struct svalue *s) } -static int low_find_shared_string_identifier(struct pike_string *name, - struct program *prog); -int find_module_identifier(struct pike_string *ident) +int low_find_shared_string_identifier(struct pike_string *name, + struct program *prog); + + + +struct node_s *find_module_identifier(struct pike_string *ident) { JMP_BUF tmp; + node *ret; if(SETJMP(tmp)) { @@ -178,7 +182,9 @@ int find_module_identifier(struct pike_string *ident) { /* fprintf(stderr,"MOD: %s, %d %d\n",ident->str, current_line, sp[-1].type); */ UNSETJMP(tmp); - return 1; + ret=mksvaluenode(sp-1); + pop_stack(); + return ret; } pop_stack(); } @@ -197,20 +203,31 @@ int find_module_identifier(struct pike_string *ident) id=ID_FROM_INT(p->new_program, i); if(IDENTIFIER_IS_CONSTANT(id->flags)) { - push_svalue(PROG_FROM_INT(p->new_program, i)->constants+ - id->func.offset); - return 1; + ret=mksvaluenode(PROG_FROM_INT(p->new_program, i)->constants+ + id->func.offset); + return ret; }else{ - yyerror("Identifier is not a constant"); - return 0; + return mkexternalnode(n, i, id); } } } } - return 0; } +struct program *parent_compilation(int level) +{ + int n; + struct program_state *p=previous_program_state; + for(n=0;n<level;n++) + { + if(n>=compilation_depth) return 0; + p=p->previous; + if(!p) return 0; + } + return p->new_program; +} + #define ID_TO_PROGRAM_CACHE_SIZE 512 struct program *id_to_program_cache[ID_TO_PROGRAM_CACHE_SIZE]; @@ -406,6 +423,8 @@ void low_start_new_program(struct program *p, i.identifier_level=0; i.storage_offset=0; i.inherit_level=0; + i.parent=0; + i.parent_identifier=0; i.name=0; add_to_inherits(i); } @@ -452,7 +471,11 @@ void really_free_program(struct program *p) free_svalue(p->constants+e); for(e=1; e<p->num_inherits; e++) + { free_program(p->inherits[e].prog); + if(p->inherits[e].parent) + free_object(p->inherits[e].parent); + } if(p->prev) p->prev->next=p->next; @@ -843,12 +866,23 @@ void rename_last_inherit(struct pike_string *n) /* * make this program inherit another program */ -void do_inherit(struct program *p,INT32 flags, struct pike_string *name) +void do_inherit(struct svalue *prog, + INT32 flags, + struct pike_string *name) { int e, inherit_offset, storage_offset; struct inherit inherit; struct pike_string *s; + struct program *p=program_from_svalue(prog); + + + if(!p) + { + yyerror("Illegal program pointer."); + return; + } + inherit_offset = new_program->num_inherits; storage_offset=new_program->storage_needed; @@ -861,7 +895,15 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) inherit.identifier_level += new_program->num_identifier_references; inherit.storage_offset += storage_offset; inherit.inherit_level ++; - + if(!e) + { + if(prog->type == T_FUNCTION) + { + inherit.parent=prog->u.object; + inherit.parent_identifier=prog->subtype; + } + } + if(inherit.parent) inherit.parent->refs++; if(name) { @@ -933,7 +975,9 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) } } -void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name) +void simple_do_inherit(struct pike_string *s, + INT32 flags, + struct pike_string *name) { reference_shared_string(s); push_string(s); @@ -952,7 +996,7 @@ void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *na free_string(s); s=name; } - do_inherit(sp[-1].u.program, flags, s); + do_inherit(sp-1, flags, s); free_string(s); pop_stack(); } @@ -1027,8 +1071,12 @@ int define_variable(struct pike_string *name, dummy.flags = 0; dummy.run_time_type=compile_type_to_runtime_type(type); - if(dummy.run_time_type == T_FUNCTION) + switch(dummy.run_time_type) + { + case T_FUNCTION: + case T_PROGRAM: dummy.run_time_type = T_MIXED; + } dummy.func.offset=add_storage(dummy.run_time_type == T_MIXED ? sizeof(struct svalue) : @@ -1335,8 +1383,8 @@ INT32 define_function(struct pike_string *name, * lookup the number of a function in a program given the name in * a shared_string */ -static int low_find_shared_string_identifier(struct pike_string *name, - struct program *prog) +int low_find_shared_string_identifier(struct pike_string *name, + struct program *prog) { int max,min,tst; struct reference *funp; @@ -1722,7 +1770,20 @@ void cleanup_program(void) void gc_mark_program_as_referenced(struct program *p) { if(gc_mark(p)) + { + int e; gc_mark_svalues(p->constants, p->num_constants); + + for(e=0;e<p->num_inherits;e++) + { + if(p->inherits[e].parent) + gc_mark_object_as_referenced(p->inherits[e].parent); + + if(e) + gc_mark_program_as_referenced(p->inherits[e].prog); + } + + } } void gc_check_all_programs(void) @@ -1730,8 +1791,30 @@ void gc_check_all_programs(void) struct program *p; for(p=first_program;p;p=p->next) { + int e; gc_check_svalues(p->constants, p->num_constants); + for(e=0;e<p->num_inherits;e++) + { + if(p->inherits[e].parent) + { +#ifdef DEBUG + if(gc_check(p->inherits[e].parent)==-2) + fprintf(stderr,"(program at 0x%lx -> inherit[%d].parent)\n", + (long)p, + e); +#else + gc_check(p->inherits[e].parent); +#endif + } + + if(d_flag && p->inherits[e].name) + gc_check(p->inherits[e].name); + + if(e) + gc_check(p->inherits[e].prog); + } + if(d_flag) { int e; @@ -1763,8 +1846,17 @@ void gc_free_all_unreferenced_programs(void) { if(gc_do_free(p)) { + int e; p->refs++; free_svalues(p->constants, p->num_constants, -1); + for(e=0;e<p->num_inherits;e++) + { + if(p->inherits[e].parent) + { + free_object(p->inherits[e].parent); + p->inherits[e].parent=0; + } + } next=p->next; free_program(p); }else{ @@ -1895,6 +1987,19 @@ struct program *program_from_function(struct svalue *f) return low_program_from_function(f->u.object->prog, f->subtype); } +struct program *program_from_svalue(struct svalue *s) +{ + switch(s->type) + { + case T_FUNCTION: + return program_from_function(s); + case T_PROGRAM: + return s->u.program; + default: + return 0; + } +} + #define FIND_CHILD_HASHSIZE 5003 struct find_child_cache_s { diff --git a/src/program.h b/src/program.h index 9eba51d6ea..45c44a4b22 100644 --- a/src/program.h +++ b/src/program.h @@ -49,6 +49,11 @@ extern char *lfun_names[]; struct svalue; #endif +#ifndef STRUCT_NODE_S_DECLARED +#define STRUCT_NODE_S_DECLARED +struct node_s; +#endif + #ifndef STRUCT_OBJECT_DECLARED #define STRUCT_OBJECT_DECLARED struct object; @@ -127,11 +132,13 @@ struct reference struct inherit { - struct program *prog; - struct pike_string *name; INT16 inherit_level; /* really needed? */ INT16 identifier_level; + INT16 parent_identifier; INT32 storage_offset; + struct object *parent; + struct program *prog; + struct pike_string *name; }; /* program parts have been realloced into one block */ @@ -197,7 +204,8 @@ extern int compiler_pass; void ins_int(INT32 i, void (*func)(char tmp)); void ins_short(INT16 i, void (*func)(char tmp)); void use_module(struct svalue *s); -int find_module_identifier(struct pike_string *ident); +struct node_s *find_module_identifier(struct pike_string *ident); +struct program *parent_compilation(int level); struct program *id_to_program(INT32 id); void optimize_program(struct program *p); void fixate_program(void); @@ -218,8 +226,12 @@ int low_reference_inherited_identifier(int e, int reference_inherited_identifier(struct pike_string *super_name, struct pike_string *function_name); void rename_last_inherit(struct pike_string *n); -void do_inherit(struct program *p,INT32 flags, struct pike_string *name); -void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name); +void do_inherit(struct svalue *prog, + INT32 flags, + struct pike_string *name); +void simple_do_inherit(struct pike_string *s, + INT32 flags, + struct pike_string *name); int isidentifier(struct pike_string *s); int define_variable(struct pike_string *name, struct pike_string *type, @@ -252,6 +264,8 @@ INT32 define_function(struct pike_string *name, INT16 flags, INT8 function_flags, union idptr *func); +int low_find_shared_string_identifier(struct pike_string *name, + struct program *prog); struct ff_hash; int find_shared_string_identifier(struct pike_string *name, struct program *prog); @@ -278,6 +292,7 @@ char *get_storage(struct object *o, struct program *p); struct program *low_program_from_function(struct program *p, INT32 i); struct program *program_from_function(struct svalue *f); +struct program *program_from_svalue(struct svalue *s); struct find_child_cache_s; int find_child(struct program *parent, struct program *child); void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))); diff --git a/src/svalue.c b/src/svalue.c index 565de67fa9..09df8a58e3 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -897,7 +897,12 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num) case T_OBJECT: if(s->u.object->prog) { - gc_check(s->u.object); +#ifdef DEBUG + if(gc_check(s->u.object) == -2) + fprintf(stderr,"(in svalue at %lx, type = %d)\n",(long)s,s->type); +#else + gc_check(s->u.object); +#endif }else{ free_svalue(s); s->type=T_INT; diff --git a/src/testsuite.in b/src/testsuite.in index d796edd591..44cb55fe2c 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,9 +1,19 @@ -test_true([["$Id: testsuite.in,v 1.40.2.2 1997/06/25 22:46:46 hubbe Exp $"]]) +test_true([["$Id: testsuite.in,v 1.40.2.3 1997/06/27 06:55:22 hubbe Exp $"]]) test_eq(1e1,10.0) test_eq(1E1,10.0) test_eq(1e+1,10.0) test_eq(1.1e1,11.0) test_eq(1e-1,0.1) +test_any([[object o=class foo{int c;class bar{void create(){c++;};}}(); o->bar(); return o->c;]],1) +test_do([[add_constant("GURKA2",class foo { int c; class bar{void create() {c+=17;}}}()); ]]) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],17) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],34) + +test_do([[add_constant("GURKA2",class foo { int c; class bar{void create() { class sune { void create() {c+=17;}}(); }}}()); ]]) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],17) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],34) +test_do([[add_constant("GURKA2");]]); + test_compile_error([[void foo() { return destruct(this_object()); }]]) test_any([[class foo { constant x=17; }; class bar { inherit foo; constant x=18; }; return bar()->x;]],18) test_program([[inline string foo(string s){ while(s[0] == ' ' || s[0] == '\t') s = s[1..]; return(s); } string a() { return foo(" bar"); }]]) -- GitLab