pike.git/
src/
docode.c
Branch:
Tag:
Non-build tags
All tags
No tags
2008-01-28
2008-01-28 18:43:14 by Henrik Grubbström (Grubba) <grubba@grubba.org>
13cdf265aa940cf8e8a309a9f5be0600bf6822e7 (
148
lines) (+
147
/-
1
)
[
Show
|
Annotate
]
Branch:
7.9
Added emit_multi_assign() and support for F_MULTI_ASSIGN nodes.
Rev: src/docode.c:1.192
2:
|| 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"
638:
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;
1019:
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) {