Branch: Tag:

2013-04-27

2013-04-27 13:59:27 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Compiler: Added support for ::this_program.

This syntax refers to the previous definition of the current class
in its parent, and is typically used with inherit like:

inherit Foo;

// Override the Bar inherited from Foo.
class Bar {
// Bar is based on the implementation from Foo.
inherit ::this_program;

// ...
}

Note that this change is slightly incompatible with Pike 7.8.

1929:       /* Handle this_program */    if (ident == this_program_string) { -  node *n = mkefuncallnode("object_program", +  node *n; +  if (!state_depth && (inherit_num == -1) && colon_colon_ref && +  !TEST_COMPAT(7,8) && +  state->previous && state->previous->new_program) { +  /* ::this_program +  * +  * This refers to the previous definition of the current class +  * in its parent, and is typically used with inherit like: +  * +  * inherit Foo; +  * +  * // Override the Bar inherited from Foo. +  * class Bar { +  * // Bar is based on the implementation from Foo. +  * inherit ::this_program; +  * +  * // ... +  * } +  */ +  struct program *parent; +  struct pike_string *name = NULL; +  int e; +  int i; +  +  /* Find the name of the current class. */ +  parent = state->previous->new_program; +  for (e = parent->num_identifier_references; e--;) { +  struct identifier *id = ID_FROM_INT(parent, e); +  struct svalue *s; +  if (!IDENTIFIER_IS_CONSTANT(id->identifier_flags) || +  (id->func.const_info.offset < 0)) { +  continue; +  } +  s = &PROG_FROM_INT(parent, e)-> +  constants[id->func.const_info.offset].sval; +  if ((TYPEOF(*s) != T_PROGRAM) || +  (s->u.program != state->new_program)) { +  continue; +  } +  /* Found! */ +  name = id->name; +  break; +  } +  if (!name) { +  yyerror("Failed to find current class in its parent."); +  return NULL; +  } +  +  /* Find ::name in the parent. */ +  i = -1; +  for (e = parent->num_inherits; e--;) { +  if (parent->inherits[e].inherit_level != 1) continue; +  i = low_reference_inherited_identifier(state->previous, e, +  name, SEE_PROTECTED); +  if (i != -1) break; +  } +  if (i == -1) { +  my_yyerror("Failed to find previous inherited definition of %S " +  "in parent.", name); +  return NULL; +  } +  n = mkexternalnode(parent, i); +  } else { +  n = mkefuncallnode("object_program",    mkthisnode(state->new_program, inherit_num)); -  +  }    /* We know this expression is constant. */    n->node_info &= ~OPT_NOT_CONST;    n->tree_info &= ~OPT_NOT_CONST;