diff --git a/src/docode.c b/src/docode.c index fb882687a0cfcb94d9f0996a3b35211ccf3147da..ed41649493a3f49d03b471ab552eebd39a5e2252 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.33 1998/03/01 11:40:46 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.34 1998/03/31 21:52:16 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.h" @@ -989,11 +989,46 @@ static int do_docode2(node *n,int flags) fatal("Bugg in F_ARROW, index not string."); if(flags & DO_LVALUE) { - /* FIXME!!!! */ + /* FIXME!!!! ??? I wonder what needs fixing... /Hubbe */ tmp1=do_docode(CAR(n), 0); emit(F_ARROW_STRING, store_prog_string(CDR(n)->u.sval.u.string)); return 2; }else{ + struct program *p; + if(CAR(n) && + CDR(n) && + EXTRACT_UCHAR(CAR(n)->type->str)==T_OBJECT && + (tmp2=EXTRACT_INT(CAR(n)->type->str+1)) && + (p=id_to_program(tmp2)) && + (FIND_LFUN(p,LFUN_ARROW)==-1) && + CDR(n)->token == F_CONSTANT && + CDR(n)->u.sval.type==T_STRING) + { + tmp3=find_shared_string_identifier(CDR(n)->u.sval.u.string,p); + if(tmp3==-1) + { + yywarning("Accessing a non-existant identifier"); + DO_CODE_BLOCK(CAR(n)); + emit(F_NUMBER,0); + return 1; + }else{ + struct identifier *i=ID_FROM_INT(p,tmp3); + if(IDENTIFIER_IS_FUNCTION(i->identifier_flags)) + { + tmp1=do_docode(CAR(n), DO_NOT_COPY); + emit(F_STRICT_ARROW, tmp3); + emit(F_DATA, tmp2); + return tmp1; + } + if(IDENTIFIER_IS_VARIABLE(i->identifier_flags)) + { + tmp1=do_docode(CAR(n), DO_NOT_COPY); + emit(F_STRICT_ARROW_VARIABLE, tmp3); + emit(F_DATA, tmp2); + return tmp1; + } + } + } tmp1=do_docode(CAR(n), DO_NOT_COPY); emit(F_ARROW, store_prog_string(CDR(n)->u.sval.u.string)); if(!(flags & DO_NOT_COPY)) diff --git a/src/interpret.c b/src/interpret.c index 666a33f7f4bfe042172d5603cb6a9771212ac829..81256f565b6411880baceb385524056b27bcb98a 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.71 1998/03/26 05:37:50 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.72 1998/03/31 21:52:17 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -580,6 +580,8 @@ static int eval_instruction(unsigned char *pc) CASE(F_NEG_NUMBER); push_int(-GET_ARG()); break; /* The rest of the basic 'push value' instructions */ + + CASE(F_MARK_AND_STRING); *(mark_sp++)=sp; CASE(F_STRING); copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]); sp->type=T_STRING; @@ -757,6 +759,20 @@ static int eval_instruction(unsigned char *pc) fp->locals[instr+1].u.integer=0; break; + CASE(F_CLEAR_4_LOCAL); + { + int e; + instr=GET_ARG(); + free_svalues(fp->locals + instr, 4, -1); + for(e=0;e<4;e++) + { + fp->locals[instr+e].type=T_INT; + fp->locals[instr+e].subtype=0; + fp->locals[instr+e].u.integer=0; + } + break; + } + CASE(F_CLEAR_LOCAL); instr=GET_ARG(); free_svalue(fp->locals + instr); @@ -1038,10 +1054,18 @@ static int eval_instruction(unsigned char *pc) pop_n_elems(3); break; + CASE(F_APPLY_ASSIGN_LOCAL); + strict_apply_svalue(fp->context.prog->constants + GET_ARG(), sp - *--mark_sp ); + /* Fall through */ + CASE(F_ASSIGN_LOCAL); assign_svalue(fp->locals+GET_ARG(),sp-1); break; + CASE(F_APPLY_ASSIGN_LOCAL_AND_POP); + strict_apply_svalue(fp->context.prog->constants + GET_ARG(), sp - *--mark_sp ); + /* Fall through */ + CASE(F_ASSIGN_LOCAL_AND_POP); instr=GET_ARG(); free_svalue(fp->locals+instr); @@ -1101,6 +1125,7 @@ static int eval_instruction(unsigned char *pc) CASE(F_POP_N_ELEMS); pop_n_elems(GET_ARG()); break; CASE(F_MARK2); *(mark_sp++)=sp; CASE(F_MARK); *(mark_sp++)=sp; break; + CASE(F_MARK_X); *(mark_sp++)=sp-GET_ARG(); break; CASE(F_CLEAR_STRING_SUBTYPE); if(sp[-1].type==T_STRING) sp[-1].subtype=0; @@ -1131,6 +1156,16 @@ static int eval_instruction(unsigned char *pc) pop_stack(); break; + CASE(F_BRANCH_IF_LOCAL); + instr=GET_ARG(); + if(IS_ZERO(fp->locals + instr)) + { + pc+=sizeof(INT32); + }else{ + DOJUMP(); + } + break; + CJUMP(F_BRANCH_WHEN_EQ, is_eq); CJUMP(F_BRANCH_WHEN_NE,!is_eq); CJUMP(F_BRANCH_WHEN_LT, is_lt); @@ -1265,6 +1300,12 @@ static int eval_instruction(unsigned char *pc) return args+1; } + CASE(F_RETURN_LOCAL); + instr=GET_ARG(); + pop_n_elems(sp-1 - (fp->locals+instr)); + print_return_value(); + goto do_return; + CASE(F_RETURN_1); push_int(1); goto do_return; @@ -1353,12 +1394,50 @@ static int eval_instruction(unsigned char *pc) push_array_items(sp->u.array); break; + CASE(F_STRICT_ARROW); + if(sp[-1].type != T_OBJECT) + error("Expected object for first argument to `->\n"); + if(!sp[-1].u.object->prog) + error("`-> on destructed object.\n"); + sp[-1].subtype=GET_ARG(); + if(sp[-1].u.object->prog->id != EXTRACT_INT(pc)) + error("`->: Object not of specified type.\n"); + sp[-1].type=T_FUNCTION; + pc+=sizeof(INT32); + break; + + CASE(F_STRICT_ARROW_VARIABLE); + if(sp[-1].type != T_OBJECT) + error("Expected object for first argument to `->\n"); + if(!sp[-1].u.object->prog) + error("`-> on destructed object.\n"); + instr=GET_ARG(); + if(sp[-1].u.object->prog->id != EXTRACT_INT(pc)) + error("`->: Object not of specified type.\n"); + pc+=sizeof(INT32); + low_object_index_no_free(sp,sp[-1].u.object,instr); + free_object(sp[-1].u.object); + sp[-1]=*sp; + break; + + CASE(F_LOCAL_LOCAL_INDEX); + { + struct svalue *s=fp->locals+GET_ARG(); + if(s->type == T_STRING) s->subtype=0; + sp++->type=T_INT; + index_no_free(sp-1,fp->locals+GET_ARG(),s); + break; + } + CASE(F_LOCAL_INDEX); - assign_svalue_no_free(sp++,fp->locals+GET_ARG()); - if(sp[-1].type == T_STRING) - sp[-1].subtype=0; - print_return_value(); - goto do_index; + { + struct svalue tmp,*s=fp->locals+GET_ARG(); + if(s->type == T_STRING) s->subtype=0; + index_no_free(&tmp,sp-1,s); + free_svalue(sp-1); + sp[-1]=tmp; + break; + } CASE(F_POS_INT_INDEX); push_int(GET_ARG()); diff --git a/src/language.yacc b/src/language.yacc index 4bfa60e1605264be49b0af1ccb0f4259c7a635c7..a224cb26bca20853c2643f3040e0f02280873534 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -10,20 +10,24 @@ */ %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 F_LDA +%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 F_MARK_X F_LDA %token F_CALL_LFUN F_CALL_LFUN_AND_POP F_CALL_LFUN_AND_RETURN %token F_APPLY F_APPLY_AND_POP F_MARK_APPLY F_MARK_APPLY_POP -%token F_APPLY_AND_RETURN +%token F_APPLY_AND_RETURN F_MARK_AND_STRING +%token F_APPLY_ASSIGN_LOCAL F_APPLY_ASSIGN_LOCAL_AND_POP %token F_BRANCH F_BRANCH_WHEN_ZERO F_BRANCH_WHEN_NON_ZERO %token F_BRANCH_WHEN_LT F_BRANCH_WHEN_GT %token F_BRANCH_WHEN_LE F_BRANCH_WHEN_GE %token F_BRANCH_WHEN_EQ F_BRANCH_WHEN_NE +%token F_BRANCH_IF_LOCAL %token F_INC_LOOP F_DEC_LOOP %token F_INC_NEQ_LOOP F_DEC_NEQ_LOOP %token F_INDEX F_ARROW F_INDIRECT F_STRING_INDEX F_LOCAL_INDEX -%token F_POS_INT_INDEX F_NEG_INT_INDEX +%token F_LOCAL_LOCAL_INDEX +%token F_POS_INT_INDEX F_NEG_INT_INDEX F_STRICT_ARROW +%token F_STRICT_ARROW_VARIABLE %token F_LTOSVAL F_LTOSVAL2 %token F_PUSH_ARRAY %token F_RANGE F_COPY_VALUE @@ -35,7 +39,8 @@ %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_CLEAR_LOCAL F_CLEAR_2_LOCAL F_CLEAR_4_LOCAL +%token 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 /* @@ -45,7 +50,8 @@ %token F_INC F_DEC F_POST_INC F_POST_DEC F_INC_AND_POP F_DEC_AND_POP %token F_INC_LOCAL F_INC_LOCAL_AND_POP F_POST_INC_LOCAL %token F_DEC_LOCAL F_DEC_LOCAL_AND_POP F_POST_DEC_LOCAL -%token F_RETURN F_DUMB_RETURN F_RETURN_0 F_RETURN_1 F_THROW_ZERO +%token F_RETURN F_DUMB_RETURN F_RETURN_0 F_RETURN_1 F_RETURN_LOCAL +%token F_THROW_ZERO %token F_ASSIGN F_ASSIGN_AND_POP %token F_ASSIGN_LOCAL F_ASSIGN_LOCAL_AND_POP @@ -89,7 +95,7 @@ %token F_DO %token F_DOT_DOT %token F_DOT_DOT_DOT -%token F_PREDEF +%token F_REDEF %token F_EFUN_CALL %token F_ELSE %token F_FLOAT_ID @@ -120,6 +126,7 @@ %token F_PRIVATE %token F_PROGRAM_ID %token F_PROTECTED +%token F_PREDEF %token F_PUBLIC %token F_RSH_EQ %token F_STATIC @@ -139,6 +146,7 @@ %token F_POINTER %token F_LABEL %token F_BYTE +%token F_DATA %token F_MAX_INSTR @@ -161,7 +169,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.66 1998/03/04 23:49:54 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.67 1998/03/31 21:52:19 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif diff --git a/src/lex.c b/src/lex.c index ec595c996f7f7fb719a127028da2e4b423d6ec4c..6eaac9eff4dac330ac6ba5cb560f570f5c113fb3 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.45 1998/03/22 06:19:37 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.46 1998/03/31 21:52:20 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -38,6 +38,10 @@ RCSID("$Id: lex.c,v 1.45 1998/03/22 06:19:37 hubbe Exp $"); #define LEXDEBUG 0 +#ifdef INSTR_PROFILING +int last_instruction=0; +#endif + void exit_lex(void) { #ifdef DEBUG @@ -52,6 +56,16 @@ void exit_lex(void) (long)instrs[e].runs, (long)instrs[e].compiles); } + +#ifdef INSTR_PROFILING + for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) + { + int d; + for(d=0;d<256;d++) + if(instrs[e].reruns[d]) + fprintf(stderr,"%010ld::%s - %s\n",instrs[e].reruns[d],low_get_f_name(e+F_OFFSET,0),low_get_f_name(d+F_OFFSET,0)); + } +#endif } #endif } @@ -115,13 +129,16 @@ struct keyword instr_names[]= { "for", F_FOR }, { "global", F_GLOBAL, I_HASARG }, { "index", F_INDEX }, -{ "->", F_ARROW, I_HASARG }, +{ "->x", F_ARROW, I_HASARG }, +{ "object(const)->func", F_STRICT_ARROW, I_HASARG }, +{ "object(const)->var", F_STRICT_ARROW_VARIABLE, I_HASARG }, { "clear string subtype", F_CLEAR_STRING_SUBTYPE }, { "arrow string", F_ARROW_STRING, I_HASARG }, { "indirect", F_INDIRECT }, { "branch", F_BRANCH, I_ISJUMP }, { "branch non zero", F_BRANCH_WHEN_NON_ZERO, I_ISJUMP }, +{ "branch if local", F_BRANCH_IF_LOCAL, I_HASARG }, { "branch when zero", F_BRANCH_WHEN_ZERO, I_ISJUMP }, { "branch if <", F_BRANCH_WHEN_LT, I_ISJUMP }, { "branch if >", F_BRANCH_WHEN_GT, I_ISJUMP }, @@ -139,7 +156,8 @@ struct keyword instr_names[]= { "==&&", F_EQ_AND, I_ISJUMP }, { "catch", F_CATCH, I_ISJUMP }, { "foreach", F_FOREACH, I_ISJUMP }, -{ "data", F_POINTER, I_ISPOINTER }, +{ "pointer", F_POINTER, I_ISPOINTER }, +{ "data", F_DATA, I_DATA }, { "local function call",F_CALL_LFUN, I_HASARG }, { "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG }, @@ -153,6 +171,7 @@ struct keyword instr_names[]= { "lvalue to svalue", F_LTOSVAL }, { "lvalue_list", F_LVALUE_LIST }, { "[ lvalues ]", F_ARRAY_LVALUE, I_HASARG }, +{ "mark sp-X", F_MARK_X, I_HASARG }, { "mark", F_MARK }, { "mark mark", F_MARK2 }, { "negative number", F_NEG_NUMBER, I_HASARG }, @@ -166,6 +185,7 @@ struct keyword instr_names[]= { "return", F_RETURN }, { "return 0", F_RETURN_0 }, { "return 1", F_RETURN_1 }, +{ "return local", F_RETURN_LOCAL, I_HASARG }, { "sscanf", F_SSCANF, I_HASARG }, { "string", F_STRING, I_HASARG }, { "switch", F_SWITCH, I_HASARG }, @@ -183,6 +203,7 @@ struct keyword instr_names[]= { "call", F_APPLY, I_HASARG }, { "clear local", F_CLEAR_LOCAL, I_HASARG }, { "clear 2 local", F_CLEAR_2_LOCAL, I_HASARG }, +{ "clear 4 local", F_CLEAR_4_LOCAL, I_HASARG }, { "++local", F_INC_LOCAL, I_HASARG }, { "++local and pop", F_INC_LOCAL_AND_POP, I_HASARG }, { "local++", F_POST_INC_LOCAL, I_HASARG }, @@ -194,6 +215,7 @@ struct keyword instr_names[]= { "throw(0)", F_THROW_ZERO }, { "string index", F_STRING_INDEX, I_HASARG }, { "local index", F_LOCAL_INDEX, I_HASARG }, +{ "local local index", F_LOCAL_LOCAL_INDEX, I_HASARG }, { "int index", F_POS_INT_INDEX, I_HASARG }, { "-int index", F_NEG_INT_INDEX, I_HASARG }, { "apply and pop", F_APPLY_AND_POP, I_HASARG }, @@ -202,9 +224,12 @@ struct keyword instr_names[]= { "nop", F_NOP }, { "add integer", F_ADD_INT, I_HASARG }, { "add -integer", F_ADD_NEG_INT, I_HASARG }, +{ "mark & string", F_MARK_AND_STRING, I_HASARG }, { "mark & call", F_MARK_APPLY, I_HASARG }, { "mark, call & pop", F_MARK_APPLY_POP, I_HASARG }, { "apply and return", F_APPLY_AND_RETURN, I_HASARG }, +{ "apply, assign local and pop", F_APPLY_ASSIGN_LOCAL_AND_POP, I_HASARG }, +{ "apply & assign local", F_APPLY_ASSIGN_LOCAL, I_HASARG }, { "call lfun & return", F_CALL_LFUN_AND_RETURN, I_HASARG }, { "call function", F_CALL_FUNCTION, 0 }, { "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 }, diff --git a/src/lex.h b/src/lex.h index ece7851d1fe78125f7de8b7dd7e67347b9c067af..aa4e1b1927b652c66a9de6be20a4a74c22ecf541 100644 --- a/src/lex.h +++ b/src/lex.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: lex.h,v 1.10 1998/03/28 15:13:07 grubba Exp $ + * $Id: lex.h,v 1.11 1998/03/31 21:52:21 hubbe Exp $ */ #ifndef LEX_H #define LEX_H @@ -24,10 +24,22 @@ struct keyword #define I_JUMP 4 #define I_ISPOINTER 3 #define I_ISJUMP 7 +#define I_DATA 9 + +#ifdef DEBUG +#define INSTR_PROFILING +#endif + +#ifdef INSTR_PROFILING +extern int last_instruction; +#endif struct instr { #ifdef DEBUG +#ifdef INSTR_PROFILING + long reruns[256]; +#endif long runs; long compiles; #endif @@ -37,7 +49,11 @@ struct instr #ifdef DEBUG #define ADD_COMPILED(X) instrs[(X)-F_OFFSET].compiles++ +#ifdef INSTR_PROFILING +#define ADD_RUNNED(X) do { int _x=(X)-F_OFFSET; instrs[last_instruction].reruns[_x]++; instrs[last_instruction=_x].runs++; } while(0) +#else #define ADD_RUNNED(X) instrs[(X)-F_OFFSET].runs++ +#endif #else #define ADD_COMPILED(X) #define ADD_RUNNED(X) diff --git a/src/main.c b/src/main.c index 56c9cdf740b16c04486d675719e8bbfd2f290b99..871846e28b2b3a890d2958269b623ccfcd68665b 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.43 1998/03/22 06:20:44 hubbe Exp $"); +RCSID("$Id: main.c,v 1.44 1998/03/31 21:52:21 hubbe Exp $"); #include "fdlib.h" #include "backend.h" #include "module.h" @@ -199,9 +199,14 @@ int dbm_main(int argc, char **argv) case 's': debug_options|=DEBUG_SIGNALS; p++; - if(p[1]) goto more_d_flags; + d_flag--; + goto more_d_flags; + + case 't': + debug_options|=NO_TAILRECURSION; p++; - break; + d_flag--; + goto more_d_flags; default: d_flag++,p++; diff --git a/src/main.h b/src/main.h index 31ceea31b78d54096d7852edb6ba0509c499dff9..f5f80f180dfd779785d552307450c477c01410ee 100644 --- a/src/main.h +++ b/src/main.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: main.h,v 1.7 1998/03/28 15:12:14 grubba Exp $ + * $Id: main.h,v 1.8 1998/03/31 21:52:22 hubbe Exp $ */ #ifndef MAIN_H #define MAIN_H @@ -15,6 +15,7 @@ extern int d_flag, t_flag, a_flag, l_flag, c_flag, p_flag, debug_options; #define DEBUG_SIGNALS 1 +#define NO_TAILRECURSION 2 /* Prototypes begin here */ struct callback *add_post_master_callback(callback_func call, diff --git a/src/peep.c b/src/peep.c index 4369524f92c7f6c616264009fa8a56989ba19eb9..c730f23c385ff766270584098a80559c1a5ea6d7 100644 --- a/src/peep.c +++ b/src/peep.c @@ -12,7 +12,7 @@ #include "peep.h" #include "dmalloc.h" -RCSID("$Id: peep.c,v 1.19 1998/03/28 15:11:56 grubba Exp $"); +RCSID("$Id: peep.c,v 1.20 1998/03/31 21:52:23 hubbe Exp $"); struct p_instr_s { @@ -258,6 +258,10 @@ void assemble(void) add_to_program(c->arg); break; + case F_DATA: + ins_int(c->arg, (void(*)(char))add_to_program); + break; + case F_LABEL: #ifdef DEBUG if(c->arg > max_label || c->arg < 0) @@ -283,9 +287,9 @@ void assemble(void) jumps[c->arg]=tmp; break; - case I_HASARG: - ins_f_byte_with_arg(c->opcode, c->arg); - break; + case I_HASARG: + ins_f_byte_with_arg(c->opcode, c->arg); + break; case 0: ins_f_byte(c->opcode); @@ -345,7 +349,6 @@ int insopt(int f, INT32 b, int cl, struct pike_string *cf) { MEMMOVE(p-fifo_len+1,p-fifo_len,fifo_len*sizeof(p_instr)); p-=fifo_len; - fifo_len++; } #ifdef DEBUG @@ -367,7 +370,7 @@ int insopt2(int f, int cl, struct pike_string *cf) if(hasarg(f)) fatal("hasarg() is wrong!\n"); #endif - return insert_opcode(f,0,cl, cf); + return insopt(f,0,cl, cf); } diff --git a/src/peep.in b/src/peep.in index 01b470eacb9c7be03a94606d4f9085ab7ca3bc97..80526b2a3f2dabdddff8cab4cdb4c9a6eda60bd6 100644 --- a/src/peep.in +++ b/src/peep.in @@ -1,5 +1,5 @@ # -# $Id: peep.in,v 1.12 1998/03/28 15:47:46 grubba Exp $ +# $Id: peep.in,v 1.13 1998/03/31 21:52:23 hubbe Exp $ # NOP : POP_N_ELEMS (0) : @@ -34,6 +34,7 @@ NEGATE CONST1 SUBTRACT : COMPL CONST0 ASSIGN_LOCAL_AND_POP : CLEAR_LOCAL($2a) CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a) : CLEAR_LOCAL($1a) CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a+1) : CLEAR_2_LOCAL($1a) +CLEAR_2_LOCAL CLEAR_2_LOCAL($1a+2) : CLEAR_4_LOCAL($1a) #CONST_1 MULTIPLY : NEGATE #CONST0 MULTIPLY : POP_VALUE CONST0 @@ -60,6 +61,8 @@ NOT BRANCH_WHEN_ZERO: BRANCH_WHEN_NON_ZERO($2a) BRANCH !LABEL : BRANCH($1a) RETURN !LABEL : RETURN RETURN_0 !LABEL : RETURN_0 +RETURN_1 !LABEL : RETURN_1 +RETURN_LOCAL !LABEL : RETURN_LOCAL($1a) BRANCH LABEL ($1a) : LABEL ($1a) LOCAL_LVALUE INC : INC_LOCAL ($1a) @@ -74,11 +77,7 @@ LOCAL_LVALUE DEC_AND_POP : DEC_LOCAL_AND_POP ($1a) DEC_LOCAL POP_VALUE : DEC_LOCAL_AND_POP ($1a) POST_DEC_LOCAL POP_VALUE : DEC_LOCAL_AND_POP ($1a) -ASSIGN_LOCAL_AND_POP LOCAL ($1a) : ASSIGN_LOCAL ($1a) ASSIGN_LOCAL_AND_POP LOCAL ($1a) RETURN : RETURN -ASSIGN_GLOBAL_AND_POP GLOBAL ($1a) : ASSIGN_GLOBAL ($1a) -DEC_LOCAL_AND_POP LOCAL ($1a) : DEC_LOCAL ($1a) -INC_LOCAL_AND_POP LOCAL ($1a) : INC_LOCAL ($1a) GLOBAL_LVALUE INC_AND_POP GLOBAL($1a): GLOBAL_LVALUE($1a) INC GLOBAL_LVALUE DEC_AND_POP GLOBAL($1a): GLOBAL_LVALUE($1a) DEC @@ -114,9 +113,11 @@ GE NOT: LT LOCAL LOCAL [$2a<256 && $3o != F_SIZEOF && $3o != F_INDEX ]: 2_LOCALS ($1a) BYTE ($2a) MARK LOCAL [ $3o != F_SIZEOF && $3o != F_INDEX ]: MARK_AND_LOCAL ($2a) +MARK STRING : MARK_AND_STRING($2a) LOCAL SIZEOF: SIZEOF_LOCAL ($1a) STRING INDEX: STRING_INDEX ($1a) LOCAL INDEX: LOCAL_INDEX ($1a) +LOCAL LOCAL INDEX: LOCAL_LOCAL_INDEX($2a) BYTE($1a) CONST0 INDEX: POS_INT_INDEX (0) CONST_1 INDEX: NEG_INT_INDEX (1) CONST1 INDEX: POS_INT_INDEX (1) @@ -154,6 +155,49 @@ NUMBER [$1a < 0] SUBTRACT : ADD_INT (-$1a) LTOSVAL2 ADD ASSIGN_AND_POP : ADD_TO_AND_POP LTOSVAL ADD ASSIGN_AND_POP : ADD_TO_AND_POP -APPLY RETURN : APPLY_AND_RETURN($1a) -CALL_FUNCTION RETURN : CALL_FUNCTION_AND_RETURN -CALL_LFUN RETURN : CALL_LFUN_AND_RETURN($1a) +APPLY [ !(debug_options & NO_TAILRECURSION) ] RETURN : APPLY_AND_RETURN($1a) +CALL_FUNCTION [ !(debug_options & NO_TAILRECURSION) ] RETURN : CALL_FUNCTION_AND_RETURN +CALL_LFUN [ !(debug_options & NO_TAILRECURSION) ] RETURN : CALL_LFUN_AND_RETURN($1a) + +LOCAL RETURN : RETURN_LOCAL($1a) +APPLY ASSIGN_LOCAL_AND_POP : APPLY_ASSIGN_LOCAL_AND_POP($1a) BYTE($2a) +ASSIGN_LOCAL_AND_POP INC_LOCAL_AND_POP($1a) : ADD_INT(1) ASSIGN_LOCAL_AND_POP($1a) +ASSIGN_LOCAL_AND_POP DEC_LOCAL_AND_POP($1a) : ADD_NEG_INT(1) ASSIGN_LOCAL_AND_POP($1a) +NUMBER ADD_INT: NUMBER($1a+$2a) +NUMBER ADD_NEG_INT: NUMBER($1a-$2a) +NEG_NUMBER ADD_INT: NUMBER($-1a+$2a) +NEG_NUMBER ADD_NEG_INT: NUMBER(-$1a-$2a) + +LOCAL BRANCH_WHEN_NON_ZERO : BRANCH_IF_LOCAL($1a) POINTER($2a) + +DEC_LOCAL_AND_POP LOCAL ($1a) : DEC_LOCAL ($1a) +INC_LOCAL_AND_POP LOCAL ($1a) : INC_LOCAL ($1a) +ASSIGN_LOCAL_AND_POP LOCAL($1a) : ASSIGN_LOCAL($1a) +ASSIGN_GLOBAL_AND_POP GLOBAL($1a) : ASSIGN_GLOBAL($1a) +APPLY_ASSIGN_LOCAL_AND_POP BYTE LOCAL ($2a) : APPLY_ASSIGN_LOCAL($1a) BYTE($2a) + +DEC_LOCAL_AND_POP MARK_AND_LOCAL ($1a) : MARK DEC_LOCAL ($1a) +INC_LOCAL_AND_POP MARK_AND_LOCAL ($1a) : MARK INC_LOCAL ($1a) +ASSIGN_GLOBAL_AND_POP MARK GLOBAL($1a) : MARK_X(1) ASSIGN_GLOBAL($1a) +ASSIGN_LOCAL_AND_POP MARK_AND_LOCAL($1a) : MARK_X(1) ASSIGN_LOCAL($1a) +APPLY_ASSIGN_LOCAL_AND_POP BYTE MARK_AND_LOCAL ($2a) : APPLY_ASSIGN_LOCAL($1a) BYTE($2a) MARK_X(1) + +ASSIGN_LOCAL ASSIGN_LOCAL($1a) : ASSIGN_LOCAL($1a) + +# MARK_X rules +MARK_X(0) : MARK +LOCAL MARK_X [$2a>0] : MARK_X($2a-1) LOCAL($1a) +STRING MARK_X [$2a>0] : MARK_X($2a-1) STRING($1a) +NUMBER MARK_X [$2a>0] : MARK_X($2a-1) NUMBER($1a) +CONST0 MARK_X [$2a>0] : MARK_X($2a-1) CONST0 +CONST1 MARK_X [$2a>0] : MARK_X($2a-1) CONST1 +CONST_1 MARK_X [$2a>0] : MARK_X($2a-1) CONST_1 +NEG_NUMBER MARK_X [$2a>0] : MARK_X($2a-1) NEG_NUMBER($1a) +GLOBAL MARK_X [$2a>0] : MARK_X($2a-1) GLOBAL($1a) +MARK_APPLY MARK_X [$2a>0] : MARK_X($2a-1) MARK_APPLY($1a) +CONSTANT MARK_X [$2a>0] : MARK_X($2a-1) CONSTANT($1a) +FLOAT MARK_X [$2a>0] : MARK_X($2a-1) FLOAT($1a) +LFUN MARK_X [$2a>0] : MARK_X($2a-1) LFUN($1a) +LTOSVAL MARK_X [$2a>0] : MARK_X($2a-1) LTOSVAL +LOCAL_LVALUE MARK_X [$2a>1] : MARK_X($2a-2) LOCAL_LVALUE($1a) +2_LOCALS BYTE MARK_X [$2a>0] : LOCAL($1a) MARK_X($3a-1) LOCAL($2a)