pike.git/src/docode.c:1:
/*
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
- || $Id: docode.c,v 1.191 2007/12/17 18:02:35 grubba Exp $
+ || $Id: docode.c,v 1.192 2008/01/28 18:43:14 grubba Exp $
*/
#include "global.h"
#include "las.h"
#include "program.h"
#include "pike_types.h"
#include "stralloc.h"
#include "interpret.h"
#include "constants.h"
#include "array.h"
pike.git/src/docode.c:631: Inside #if defined(PIKE_DEBUG)
}
if (num_args != expected_args)
Pike_fatal ("Wrong number of args to o_range opcode. Expected %d, got %d.\n",
expected_args, num_args);
}
#endif
emit1 (F_RANGE, bound_types);
}
+ static void emit_multi_assign(node *vals, node *vars, int no)
+ {
+ node *var;
+ node *val;
+ node **valp = my_get_arg(&vals, no);
+
+ fprintf(stderr, "emit_multi_assign(%p, %p)\n", vals, vars);
+
+ if (!vars && (!valp || !*valp)) return;
+ if (!(vars && valp && (val = *valp))) {
+ yyerror("Argument count mismatch for multi-assignment.\n");
+ return;
+ }
+
+ if (vars->token == F_LVALUE_LIST) {
+ var = CAR(vars);
+ vars = CDR(vars);
+ } else {
+ var = vars;
+ vars = NULL;
+ }
+
+ switch(var->token) {
+ case F_LOCAL:
+ if(var->u.integer.a >=
+ find_local_frame(CDR(var)->u.integer.b)->max_number_of_locals)
+ yyerror("Illegal to use local variable here.");
+
+ if(var->u.integer.b) goto normal_assign;
+
+ if (var->node_info & OPT_ASSIGNMENT) {
+ /* Initialize. */
+ emit0(F_CONST0);
+ emit1(F_ASSIGN_LOCAL_AND_POP, var->u.integer.a);
+ }
+ code_expression(val, 0, "RHS");
+ emit_multi_assign(vals, vars, no+1);
+ emit1(F_ASSIGN_LOCAL_AND_POP, var->u.integer.a );
+ break;
+
+ /* FIXME: Make special case for F_EXTERNAL */
+ case F_IDENTIFIER:
+ if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(Pike_compiler->new_program,
+ var->u.id.number)->identifier_flags))
+ {
+ yyerror("Cannot assign functions or constants.\n");
+ }else{
+ code_expression(val, 0, "RHS");
+ emit_multi_assign(vals, vars, no+1);
+ emit1(F_ASSIGN_GLOBAL_AND_POP, var->u.id.number);
+ }
+ break;
+
+ case F_GET_SET:
+ {
+ /* Check for the setter function. */
+ struct program_state *state = Pike_compiler;
+ int program_id = var->u.integer.a;
+ int level = 0;
+ while (state && (state->new_program->id != program_id)) {
+ state = state->previous;
+ level++;
+ }
+ if (!state) {
+ yyerror("Lost parent.");
+ } else {
+ struct reference *ref =
+ PTR_FROM_INT(state->new_program, var->u.integer.b);
+ struct identifier *id =
+ ID_FROM_PTR(state->new_program, ref);
+ struct inherit *inh =
+ INHERIT_FROM_PTR(state->new_program, ref);
+ int f;
+ #ifdef PIKE_DEBUG
+ if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags) ||
+ (id->run_time_type != PIKE_T_GET_SET)) {
+ Pike_fatal("Not a getter/setter in a F_GET_SET node!\n"
+ " identifier_flags: 0x%08x\n"
+ " run_time_type; %s (%d)\n",
+ id->identifier_flags,
+ get_name_of_type(id->run_time_type),
+ id->run_time_type);
+ }
+ #endif /* PIKE_DEBUG */
+ f = ((INT32 *)(inh->prog->program + id->func.offset))[1];
+ if (f == -1) {
+ yywarning("Variable %S lacks a setter.", id->name);
+ } else if (!level) {
+ f += inh->identifier_level;
+ emit0(F_MARK);
+ code_expression(val, 0, "RHS");
+ emit_multi_assign(vals, vars, no+1);
+ emit1(F_CALL_LFUN, f);
+ emit0(F_POP_VALUE);
+ }
+ }
+ }
+ /* FALL_THROUGH */
+ case F_EXTERNAL:
+ /* Check that it is in this context */
+ if(Pike_compiler ->new_program->id == var->u.integer.a)
+ {
+ /* Check that it is a variable */
+ if(var->u.integer.b != IDREF_MAGIC_THIS &&
+ IDENTIFIER_IS_VARIABLE( ID_FROM_INT(Pike_compiler->new_program, var->u.integer.b)->identifier_flags))
+ {
+ code_expression(val, 0, "RHS");
+ emit_multi_assign(vals, vars, no+1);
+ emit1(F_ASSIGN_GLOBAL_AND_POP, var->u.integer.b);
+ break;
+ }
+ }
+ /* fall through */
+
+ default:
+ normal_assign:
+ do_docode(var, DO_LVALUE);
+ if(do_docode(val, 0) != 1) yyerror("RHS is void!");
+ emit_multi_assign(vals, vars, no+1);
+ emit0(F_ASSIGN_AND_POP);
+ break;
+ }
+ }
+
static int do_docode2(node *n, int flags)
{
ptrdiff_t tmp1,tmp2,tmp3;
int ret;
if(!n) return 0;
if(flags & DO_LVALUE)
{
switch(n->token)
pike.git/src/docode.c:1012:
if(flags & DO_POP)
{
emit0(F_ASSIGN_AND_POP);
return 0;
}else{
emit0(F_ASSIGN);
return 1;
}
+ case F_MULTI_ASSIGN:
+ if (flags & DO_POP) {
+ emit_multi_assign(CAR(n), CDR(n), 0);
+ return 0;
+ } else {
+ /* Fall back to the normal assign case. */
+ tmp1=do_docode(CDR(n),DO_LVALUE);
+ #ifdef PIKE_DEBUG
+ if(tmp1 & 1)
+ Pike_fatal("Very internal compiler error.\n");
+ #endif
+ emit1(F_ARRAY_LVALUE, DO_NOT_WARN((INT32)(tmp1>>1)));
+ emit0(F_MARK);
+ PUSH_CLEANUP_FRAME(do_pop_mark, 0);
+ do_docode(CAR(n), 0);
+ emit_apply_builtin("aggregate");
+ POP_AND_DONT_CLEANUP;
+ emit0(F_ASSIGN);
+ return 1;
+ }
+
case F_ASSIGN:
switch(CAR(n)->token)
{
case F_RANGE:
case F_AND:
case F_OR:
case F_XOR:
case F_LSH:
case F_RSH:
case F_ADD: