diff --git a/src/array.c b/src/array.c index 2f7bc172f453b4b0fd085d68c1256e2018bb6490..eda13830f9f9599fbcb334848631f66638029f96 100644 --- a/src/array.c +++ b/src/array.c @@ -116,6 +116,11 @@ void really_free_array(struct array *v) array_free_no_free(v); } +void do_free_array(struct array *a) +{ + free_array(a); +} + /* * Extract an svalue from an array */ diff --git a/src/array.h b/src/array.h index 45420bdf8193e22b5f29ca6bbc6154e344bc9f24..ef2851883af8550d32d5cda3111d0705173523a2 100644 --- a/src/array.h +++ b/src/array.h @@ -25,6 +25,7 @@ struct array }; #define ARRAY_CYCLIC 1 +#define ARRAY_LVALUE 2 extern struct array empty_array; @@ -61,6 +62,7 @@ typedef short_cmpfun (*cmpfun_getter)(TYPE_T); /* Prototypes begin here */ struct array *low_allocate_array(INT32 size,INT32 extra_space); void really_free_array(struct array *v); +void do_free_array(struct array *a); void array_index_no_free(struct svalue *s,struct array *v,INT32 index); void array_index(struct svalue *s,struct array *v,INT32 index); void simple_array_index_no_free(struct svalue *s, diff --git a/src/docode.c b/src/docode.c index 7109fc59986aabc948aa22323ec3022922b4222c..8bfbd3f9731e3eb05eb89e8afaa7a7878dd991ba 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.29 1998/01/30 20:04:31 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.30 1998/02/01 04:01:32 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.h" @@ -244,20 +244,21 @@ static int do_docode2(node *n,int flags) { switch(n->token) { - default: - yyerror("Illegal lvalue."); - emit(F_NUMBER,0); - return 1; + default: + yyerror("Illegal lvalue."); + emit(F_NUMBER,0); + return 1; - case F_LVALUE_LIST: - case F_LOCAL: - case F_GLOBAL: - case F_IDENTIFIER: - case F_INDEX: - case F_ARROW: - case F_ARG_LIST: - case F_EXTERNAL: - break; + case F_ARRAY_LVALUE: + case F_LVALUE_LIST: + case F_LOCAL: + case F_GLOBAL: + case F_IDENTIFIER: + case F_INDEX: + case F_ARROW: + case F_ARG_LIST: + case F_EXTERNAL: + break; } } @@ -973,6 +974,15 @@ static int do_docode2(node *n,int flags) case F_LVALUE_LIST: return do_docode(CAR(n),DO_LVALUE)+do_docode(CDR(n),DO_LVALUE); + case F_ARRAY_LVALUE: + tmp1=do_docode(CAR(n),DO_LVALUE); +#ifdef DEBUG + if(tmp1 & 1) + fatal("Very internal compiler error.\n"); +#endif + emit(F_ARRAY_LVALUE, tmp1>>1); + return 2; + case F_ARROW: if(CDR(n)->token != F_CONSTANT || CDR(n)->u.sval.type!=T_STRING) fatal("Bugg in F_ARROW, index not string."); diff --git a/src/interpret.c b/src/interpret.c index db8dce364b23478bd17d35e2b63a4fdbf6a9de67..4933bc51e76240f6be874c919e3b5f52b3209e76 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.65 1998/02/01 02:07:24 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.66 1998/02/01 04:01:32 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -197,43 +197,58 @@ void lvalue_to_svalue_no_free(struct svalue *to,struct svalue *lval) { switch(lval->type) { - case T_LVALUE: - assign_svalue_no_free(to, lval->u.lval); - break; - - case T_SHORT_LVALUE: - assign_from_short_svalue_no_free(to, lval->u.short_lval, lval->subtype); - break; - - case T_OBJECT: - object_index_no_free(to, lval->u.object, lval+1); - break; - - case T_ARRAY: - simple_array_index_no_free(to, lval->u.array, lval+1); - break; - - case T_MAPPING: - mapping_index_no_free(to, lval->u.mapping, lval+1); - break; - - case T_MULTISET: - to->type=T_INT; - if(multiset_member(lval->u.multiset,lval+1)) + case T_ARRAY_LVALUE: { - to->u.integer=0; - to->subtype=NUMBER_UNDEFINED; - }else{ - to->u.integer=0; - to->subtype=NUMBER_NUMBER; + INT32 e; + struct array *a; + ONERROR err; + a=allocate_array(lval[1].u.array->size>>1); + SET_ONERROR(err, do_free_array, a); + for(e=0;e<a->size;e++) + lvalue_to_svalue_no_free(a->item+e, lval[1].u.array->item+(e<<1)); + to->type = T_ARRAY; + to->u.array=a; + UNSET_ONERROR(err); + break; } - break; - - default: - if(IS_ZERO(lval)) - error("Indexing the NULL value.\n"); /* Per */ - else - error("Indexing a basic type.\n"); + + case T_LVALUE: + assign_svalue_no_free(to, lval->u.lval); + break; + + case T_SHORT_LVALUE: + assign_from_short_svalue_no_free(to, lval->u.short_lval, lval->subtype); + break; + + case T_OBJECT: + object_index_no_free(to, lval->u.object, lval+1); + break; + + case T_ARRAY: + simple_array_index_no_free(to, lval->u.array, lval+1); + break; + + case T_MAPPING: + mapping_index_no_free(to, lval->u.mapping, lval+1); + break; + + case T_MULTISET: + to->type=T_INT; + if(multiset_member(lval->u.multiset,lval+1)) + { + to->u.integer=0; + to->subtype=NUMBER_UNDEFINED; + }else{ + to->u.integer=0; + to->subtype=NUMBER_NUMBER; + } + break; + + default: + if(IS_ZERO(lval)) + error("Indexing the NULL value.\n"); /* Per */ + else + error("Indexing a basic type.\n"); } } @@ -241,6 +256,20 @@ void assign_lvalue(struct svalue *lval,struct svalue *from) { switch(lval->type) { + case T_ARRAY_LVALUE: + { + INT32 e; + if(from->type != T_ARRAY) + error("Trying to assign combined lvalue from non-array.\n"); + + if(from->u.array->size < (lval[1].u.array->size>>1)) + error("Not enough values for multiple assign.\n"); + + for(e=0;e<from->u.array->size;e++) + assign_lvalue(lval[1].u.array->item+(e<<1),from->u.array->item+e); + } + break; + case T_LVALUE: assign_svalue(lval->u.lval,from); break; @@ -280,31 +309,34 @@ union anything *get_pointer_if_this_type(struct svalue *lval, TYPE_T t) { switch(lval->type) { - case T_LVALUE: - if(lval->u.lval->type == t) return & ( lval->u.lval->u ); - return 0; - - case T_SHORT_LVALUE: - if(lval->subtype == t) return lval->u.short_lval; - return 0; - - case T_OBJECT: - return object_get_item_ptr(lval->u.object,lval+1,t); - - case T_ARRAY: - return array_get_item_ptr(lval->u.array,lval+1,t); - - case T_MAPPING: - return mapping_get_item_ptr(lval->u.mapping,lval+1,t); - - case T_MULTISET: return 0; + case T_ARRAY_LVALUE: + return 0; + + case T_LVALUE: + if(lval->u.lval->type == t) return & ( lval->u.lval->u ); + return 0; + + case T_SHORT_LVALUE: + if(lval->subtype == t) return lval->u.short_lval; + return 0; + + case T_OBJECT: + return object_get_item_ptr(lval->u.object,lval+1,t); + + case T_ARRAY: + return array_get_item_ptr(lval->u.array,lval+1,t); + + case T_MAPPING: + return mapping_get_item_ptr(lval->u.mapping,lval+1,t); - default: - if(IS_ZERO(lval)) - error("Indexing the NULL value.\n"); /* Per */ + case T_MULTISET: return 0; + + default: + if(IS_ZERO(lval)) + error("Indexing the NULL value.\n"); /* Per */ else error("Indexing a basic type.\n"); - return 0; + return 0; } } @@ -732,6 +764,14 @@ static int eval_instruction(unsigned char *pc) sp+=2; break; + CASE(F_ARRAY_LVALUE); + f_aggregate(GET_ARG()*2); + sp[-1].u.array->flags |= ARRAY_LVALUE; + sp[0]=sp[-1]; + sp[-1].type=T_ARRAY_LVALUE; + sp++; + break; + CASE(F_CLEAR_2_LOCAL); instr=GET_ARG(); free_svalues(fp->locals + instr, 2, -1); @@ -1082,24 +1122,6 @@ static int eval_instruction(unsigned char *pc) } break; -#ifdef F_ASSIGN_ARRAY - CASE(F_ASSIGN_ARRAY); - { - struct svalue *base=*--mark_sp; - INT32 e,args=(sp-base)>>1 - if(sp[-1].type != T_ARRAY) - error("Bad argument to multiple assign, not an array.\n"); - if(sp[-1].u.array->size < args) - error("Not enough elements in array for multiple assign.\n"); - - for(e=0;e<args;e++) - assign_lvalue(base+e*2,sp[-1].u.array->item+e); - - pop_n_elems(sp-base); - break; - } -#endif - /* Stack machine stuff */ CASE(F_POP_VALUE); pop_stack(); break; CASE(F_POP_N_ELEMS); pop_n_elems(GET_ARG()); break; diff --git a/src/language.yacc b/src/language.yacc index b5caf9c8a24dbd53825786d7005f8c513c97de3c..732c8de4c0ec5ce85c8929085474fda86c821493 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -110,6 +110,7 @@ %token F_LOCAL %token F_LSH_EQ %token F_LVALUE_LIST +%token F_ARRAY_LVALUE %token F_MAPPING_ID %token F_MIXED_ID %token F_MOD_EQ @@ -161,7 +162,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.58 1998/01/29 17:43:21 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.59 1998/02/01 04:01:33 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -322,6 +323,7 @@ int yylex(YYSTYPE *yylval); %type <n> low_idents %type <n> lvalue %type <n> lvalue_list +%type <n> low_lvalue_list %type <n> m_expr_list %type <n> m_expr_list2 %type <n> new_local_name @@ -1146,7 +1148,9 @@ expr00: expr0 expr0: expr01 | expr4 '=' expr0 { $$=mknode(F_ASSIGN,$3,$1); } + | '[' low_lvalue_list ']' '=' expr0 { $$=mknode(F_ASSIGN,$5,mknode(F_ARRAY_LVALUE,$2,0)); } | expr4 assign expr0 { $$=mknode($2,$1,$3); } + | '[' low_lvalue_list ']' assign expr0 { $$=mknode(F_ASSIGN,mknode(F_ARRAY_LVALUE,$2,0),$5); } | error assign expr01 { $$=0; reset_type_stack(); yyerrok; } ; @@ -1432,6 +1436,7 @@ sscanf: F_SSCANF '(' expr0 ',' expr0 lvalue_list ')' ; lvalue: expr4 + | '[' low_lvalue_list ']' { $$=mknode(F_ARRAY_LVALUE, $2,0); } | type F_IDENTIFIER { add_local_name($2->u.sval.u.string,pop_type()); @@ -1439,6 +1444,10 @@ lvalue: expr4 free_node($2); } +low_lvalue_list: /* empty */ { $$=0; } + | lvalue lvalue_list { $$=mknode(F_LVALUE_LIST,$1,$2); } + ; + lvalue_list: /* empty */ { $$ = 0; } | ',' lvalue lvalue_list { $$ = mknode(F_LVALUE_LIST,$2,$3); } ; diff --git a/src/las.c b/src/las.c index 253edbcb3d74ed5696af604f4bb5409be552fa8d..f4256117201f0526fc75b23ab229d15c8284bb31 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.49 1998/01/30 05:24:34 hubbe Exp $"); +RCSID("$Id: las.c,v 1.50 1998/02/01 04:01:34 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -1028,6 +1028,12 @@ static void low_print_tree(node *foo,int needlval) low_print_tree(CDR(foo),needlval); return; + case F_ARRAY_LVALUE: + putchar('['); + low_print_tree(CAR(foo),1); + putchar(']'); + break; + case F_LVALUE_LIST: low_print_tree(CAR(foo),1); if(CAR(foo) && CDR(foo)) putchar(','); @@ -1250,6 +1256,10 @@ static void find_written_vars(node *n, find_written_vars(CDR(n), p, 1); break; + case F_ARRAY_LVALUE: + find_written_vars(CAR(n), p, 1); + break; + case F_LVALUE_LIST: find_written_vars(CAR(n), p, 1); find_written_vars(CDR(n), p, 1); diff --git a/src/lex.c b/src/lex.c index cd98754fb8bb81b3dc220507a13eb1c4eecebca9..bc5f4d3840b16f67541118f6996e8c7a5a8d9b6d 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.42 1998/01/29 06:02:29 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.43 1998/02/01 04:01:36 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -152,6 +152,7 @@ struct keyword instr_names[]= { "ltosval2", F_LTOSVAL2 }, { "lvalue to svalue", F_LTOSVAL }, { "lvalue_list", F_LVALUE_LIST }, +{ "[ lvalues ]", F_ARRAY_LVALUE, I_HASARG }, { "mark", F_MARK }, { "mark mark", F_MARK2 }, { "negative number", F_NEG_NUMBER, I_HASARG }, diff --git a/src/svalue.h b/src/svalue.h index e198ff8377757f0780018cc071934cfb38ddb85b..c525d95296b5dee951dfe48ff2dc1a7415f6bc0f 100644 --- a/src/svalue.h +++ b/src/svalue.h @@ -95,6 +95,7 @@ struct svalue #define T_OR 251 #define T_SHORT_LVALUE 252 #define T_LVALUE 253 +#define T_ARRAY_LVALUE 254 #define T_MIXED 255 #define BIT_ARRAY (1<<T_ARRAY) @@ -170,7 +171,7 @@ do{ \ }while(0) #ifdef DEBUG -#define check_type(T) if(T > MAX_TYPE && T!=T_LVALUE && T!=T_SHORT_LVALUE && T!=T_VOID && T!=T_DELETED) fatal("Type error\n") +#define check_type(T) if(T > MAX_TYPE && T!=T_LVALUE && T!=T_SHORT_LVALUE && T!=T_VOID && T!=T_DELETED && T!=T_ARRAY_LVALUE) fatal("Type error\n") #define check_refs(S) if((S)->type < MAX_REF_TYPE && (!(S)->u.refs || (S)->u.refs[0] < 0)) fatal("Svalue to object without references.\n") #define check_refs2(S,T) if((T) < MAX_REF_TYPE && (S)->refs && (S)->refs[0] <= 0) fatal("Svalue to object without references.\n")