Branch: Tag:

2007-10-05

2007-10-05 17:45:10 by Henrik Grubbström (Grubba) <grubba@grubba.org>

First go at supporting both an implicit and an explicit create() in the same program.

Rev: src/language.yacc:1.383

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: language.yacc,v 1.382 2007/09/29 15:09:03 grubba Exp $ + || $Id: language.yacc,v 1.383 2007/10/05 17:45:10 grubba Exp $   */      %pure_parser
244:   %type <number> arguments   %type <number> arguments2   %type <number> func_args - %type <number> optional_create_arguments +    %type <number> create_arguments   %type <number> create_arguments2   %type <number> create_arg
762:      def: modifiers type_or_error optional_constant optional_stars    TOK_IDENTIFIER push_compiler_frame0 -  '(' arguments close_paren_or_missing +  '('    { -  +  $<number>$ = 0; +  /* Check for the (very special) case of create and create_args. */ +  if (Pike_compiler->num_create_args) { +  struct pike_string *create_string = NULL;    int e; -  +  MAKE_CONST_STRING(create_string, "create"); +  if ($5->u.sval.u.string == create_string) { +  /* Prepend the create arguments. */ +  if (Pike_compiler->num_create_args < 0) { +  Pike_compiler->varargs = 1; +  for (e = 0; e < -Pike_compiler->num_create_args; e++) { +  struct identifier *id = +  Pike_compiler->new_program->identifiers + e; +  add_ref(id->type); +  add_local_name(id->name, id->type, 0); +  } +  } else { +  for (e = 0; e < Pike_compiler->num_create_args; e++) { +  struct identifier *id = +  Pike_compiler->new_program->identifiers + e; +  add_ref(id->type); +  add_local_name(id->name, id->type, 0); +  } +  } +  $<number>$ = e; +  } +  } +  } +  arguments close_paren_or_missing +  { +  int e;       /* Adjust opt_flags in case we've got an optional_constant. */    Pike_compiler->compiler_frame->opt_flags = $3;
782:       push_finished_type(Pike_compiler->compiler_frame->current_return_type);    -  e=$8-1; -  if(Pike_compiler->varargs) +  e = $<number>8 + $9 - 1; +  if(Pike_compiler->varargs && +  (!$<number>8 || (Pike_compiler->num_create_args >= 0)))    {    push_finished_type(Pike_compiler->compiler_frame->variable[e].type);    e--;
893:    block_or_semi    {    int e; -  if($11) +  if($12)    {    int f;    node *check_args = NULL;
908:    yywarning("Extern declared function definition.");    }    -  for(e=0; e<$8; e++) +  for(e=0; e<$<number>8+$9; e++)    {    if(!Pike_compiler->compiler_frame->variable[e].name ||    !Pike_compiler->compiler_frame->variable[e].name->len)    { -  my_yyerror("Missing name for argument %d.",e); +  my_yyerror("Missing name for argument %d.", e - $<number>8);    } else {    if (Pike_compiler->compiler_pass == 2) {    if ($1 & ID_VARIANT) {
974:    NULL));    }    +  if ($<number>8) { +  /* Hook in the initializers for the create arguments. */ +  for (e = $<number>8; e--;) { +  $12 = mknode(F_COMMA_EXPR, +  mknode(F_POP_VALUE, +  mknode(F_ASSIGN, mklocalnode(e, 0), +  mkidentifiernode(e)), NULL), +  $12); +  } +  } +     { -  int l = $11->line_number; -  struct pike_string *f = $11->current_file; +  int l = $12->line_number; +  struct pike_string *f = $12->current_file;    if (check_args) {    /* Prepend the arg checking code. */ -  $11 = mknode(F_COMMA_EXPR, mknode(F_POP_VALUE, check_args, NULL), $11); +  $12 = mknode(F_COMMA_EXPR, mknode(F_POP_VALUE, check_args, NULL), $12);    }    lex.current_line = l;    lex.current_file = f;    }       f=dooptcode(check_node_hash($5)->u.sval.u.string, -  check_node_hash($11), -  check_node_hash($<n>10)->u.sval.u.type, +  check_node_hash($12), +  check_node_hash($<n>11)->u.sval.u.type,    $1);       i = ID_FROM_INT(Pike_compiler->new_program, f);
1018:    }    pop_compiler_frame();    free_node($5); -  free_node($9); -  free_node($<n>10); +  free_node($10); +  free_node($<n>11);    }    | modifiers type_or_error optional_constant optional_stars TOK_IDENTIFIER push_compiler_frame0    error
2337:   create_arg: modifiers type_or_error optional_stars optional_dot_dot_dot TOK_IDENTIFIER    {    struct pike_type *type; +  int ref_no;    -  if (Pike_compiler->varargs) { +  if (Pike_compiler->num_create_args < 0) {    yyerror("Can't define more variables after ...");    }   
2349:    while($3--) push_type(T_ARRAY);    if ($4) {    push_type(T_ARRAY); -  Pike_compiler->varargs = 1; +     }    type=compiler_pop_type();    -  if(islocal($5->u.sval.u.string) >= 0) -  my_yyerror("Variable %S appears twice in create argument list.", -  $5->u.sval.u.string); -  -  /* Add the identifier both globally and locally. */ -  define_variable($5->u.sval.u.string, type, +  /* Add the identifier both globally. */ +  ref_no = define_variable($5->u.sval.u.string, type,    Pike_compiler->current_modifiers); -  add_local_name($5->u.sval.u.string, type, 0); +     -  +  if (Pike_compiler->num_create_args != ref_no) { +  my_yyerror("Multiple definitions of create variable %S (%d != %d).", +  $5->u.sval.u.string, +  Pike_compiler->num_create_args, ref_no); +  } +  if ($4) { +  /* Encode varargs marker as negative number of args. */ +  Pike_compiler->num_create_args = -(ref_no + 1); +  } else { +  Pike_compiler->num_create_args = ref_no + 1; +  } +     /* free_type(type); */    free_node($5);    $$=0;
2382:    | create_arguments2 optional_comma    ;    - push_compiler_frame01: /* empty */ + optional_create_arguments: /* empty */ +  | '(' create_arguments close_paren_or_missing    { -  push_compiler_frame(SCOPE_LOCAL); +  free_node($3);    }    ;    - optional_create_arguments: /* empty */ { $$ = 0; } -  | '(' push_compiler_frame01 create_arguments close_paren_or_missing + failsafe_program: '{' program end_block +  | error { yyerrok; } +  | TOK_LEX_EOF    { -  +  yyerror("End of file where program definition expected."); +  } +  ; +  + class: modifiers TOK_CLASS line_number_info optional_identifier +  { +  if(!$4) +  { +  struct pike_string *s; +  char buffer[42]; +  sprintf(buffer,"__class_%ld_%ld_line_%d", +  (long)Pike_compiler->new_program->id, +  (long)Pike_compiler->local_class_counter++, +  (int) $3->line_number); +  s=make_shared_string(buffer); +  $4=mkstrnode(s); +  free_string(s); +  $1|=ID_STATIC | ID_PRIVATE | ID_INLINE; +  } +  /* fprintf(stderr, "LANGUAGE.YACC: CLASS start\n"); */ +  if(Pike_compiler->compiler_pass==1) +  { +  if ($1 & ID_EXTERN) { +  yywarning("Extern declared class definition."); +  } +  low_start_new_program(0, 1, $4->u.sval.u.string, +  $1, +  &$<number>$); +  +  /* fprintf(stderr, "Pass 1: Program %s has id %d\n", +  $4->u.sval.u.string->str, Pike_compiler->new_program->id); */ +  +  store_linenumber($3->line_number, $3->current_file); +  debug_malloc_name(Pike_compiler->new_program, +  $3->current_file->str, +  $3->line_number); +  }else{ +  int i; +  struct identifier *id; +  int tmp=Pike_compiler->compiler_pass; +  i=isidentifier($4->u.sval.u.string); +  if(i<0) +  { +  /* Seriously broken... */ +  yyerror("Pass 2: program not defined!"); +  low_start_new_program(0, 2, 0, +  $1, +  &$<number>$); +  }else{ +  id=ID_FROM_INT(Pike_compiler->new_program, i); +  if(IDENTIFIER_IS_CONSTANT(id->identifier_flags)) +  { +  struct svalue *s; +  if ((id->func.offset >= 0) && +  ((s = &PROG_FROM_INT(Pike_compiler->new_program,i)-> +  constants[id->func.offset].sval)->type == T_PROGRAM)) +  { +  low_start_new_program(s->u.program, 2, +  $4->u.sval.u.string, +  $1, +  &$<number>$); +  +  /* fprintf(stderr, "Pass 2: Program %s has id %d\n", +  $4->u.sval.u.string->str, Pike_compiler->new_program->id); */ +  +  }else{ +  yyerror("Pass 2: constant redefined!"); +  low_start_new_program(0, 2, 0, +  $1, +  &$<number>$); +  } +  }else{ +  yyerror("Pass 2: class constant no longer constant!"); +  low_start_new_program(0, 2, 0, +  $1, +  &$<number>$); +  } +  } +  Pike_compiler->compiler_pass=tmp; +  } +  } +  { +  /* Clear scoped modifiers. */ +  $<number>$ = lex.pragmas; +  lex.pragmas &= ~ID_MODIFIER_MASK; +  } +  optional_create_arguments failsafe_program +  { +  struct program *p; +  +  /* Check if we have create arguments but no locally defined create(). */ +  if (Pike_compiler->num_create_args) { +  struct pike_string *create_string = NULL; +  struct reference *ref = NULL; +  struct identifier *id = NULL; +  int ref_id; +  MAKE_CONST_STRING(create_string, "create"); +  if (((ref_id = isidentifier(create_string)) < 0) || +  (ref = PTR_FROM_INT(Pike_compiler->new_program, ref_id))->inherit_offset || +  (id = ID_FROM_PTR(Pike_compiler->new_program, ref))->func.offset == -1) {    int e;    node *create_code = NULL;    struct pike_type *type = NULL; -  struct pike_string *create_string = NULL; +  int nargs = Pike_compiler->num_create_args;    int f;    -  MAKE_CONST_STRING(create_string, "create"); +  push_compiler_frame(SCOPE_LOCAL);    -  +  /* Init: Prepend the create arguments. */ +  if (Pike_compiler->num_create_args < 0) { +  for (e = 0; e < -Pike_compiler->num_create_args; e++) { +  id = Pike_compiler->new_program->identifiers + e; +  add_ref(id->type); +  add_local_name(id->name, id->type, 0); +  } +  } else { +  for (e = 0; e < Pike_compiler->num_create_args; e++) { +  id = Pike_compiler->new_program->identifiers + e; +  add_ref(id->type); +  add_local_name(id->name, id->type, 0); +  } +  } +     /* First: Deduce the type for the create() function. */    push_type(T_VOID); /* Return type. */ -  e = $3-1; -  if (Pike_compiler->varargs) { +  +  if ((e = nargs) < 0) {    /* Varargs */ -  push_finished_type(Pike_compiler->compiler_frame->variable[e--].type); +  e = nargs = -nargs; +  push_finished_type(Pike_compiler->compiler_frame->variable[--e].type);    pop_type_stack(T_ARRAY); /* Pop one level of array. */    } else {    /* Not varargs. */    push_type(T_VOID);    }    push_type(T_MANY); -  for(; e >= 0; e--) { +  while(e--) {    push_finished_type(Pike_compiler->compiler_frame->variable[e].type);    push_type(T_FUNCTION);    }
2424:    define_function(create_string, type,    ID_INLINE | ID_STATIC,    IDENTIFIER_PIKE_FUNCTION | -  (Pike_compiler->varargs?IDENTIFIER_VARARGS:0), +  (Pike_compiler->num_create_args < 0?IDENTIFIER_VARARGS:0),    0,    OPT_SIDE_EFFECT);    -  Pike_compiler->varargs = 0; -  +     /* Third: Generate the initialization code.    *    * global_arg = [type]local_arg;    * [,..]    */    -  for(e=0; e<$3; e++) +  for(e=0; e<nargs; e++)    {    if(!Pike_compiler->compiler_frame->variable[e].name ||    !Pike_compiler->compiler_frame->variable[e].name->len)
2464:    create_code =    mknode(F_COMMA_EXPR, create_code,    mknode(F_ASSIGN, local_node, -  mkidentifiernode(isidentifier(Pike_compiler-> -  compiler_frame-> -  variable[e].name)))); +  mkidentifiernode(e)));    }    }   
2494:       /* Done. */    -  pop_compiler_frame(); -  free_node($4); +     free_type(type); -  +  pop_compiler_frame();    } -  ; -  - failsafe_program: '{' program end_block -  | error { yyerrok; } -  | TOK_LEX_EOF -  { -  yyerror("End of file where program definition expected."); +     } -  ; +     - class: modifiers TOK_CLASS line_number_info optional_identifier -  { -  if(!$4) -  { -  struct pike_string *s; -  char buffer[42]; -  sprintf(buffer,"__class_%ld_%ld_line_%d", -  (long)Pike_compiler->new_program->id, -  (long)Pike_compiler->local_class_counter++, -  (int) $3->line_number); -  s=make_shared_string(buffer); -  $4=mkstrnode(s); -  free_string(s); -  $1|=ID_STATIC | ID_PRIVATE | ID_INLINE; -  } -  /* fprintf(stderr, "LANGUAGE.YACC: CLASS start\n"); */ -  if(Pike_compiler->compiler_pass==1) -  { -  if ($1 & ID_EXTERN) { -  yywarning("Extern declared class definition."); -  } -  low_start_new_program(0, 1, $4->u.sval.u.string, -  $1, -  &$<number>$); -  -  /* fprintf(stderr, "Pass 1: Program %s has id %d\n", -  $4->u.sval.u.string->str, Pike_compiler->new_program->id); */ -  -  store_linenumber($3->line_number, $3->current_file); -  debug_malloc_name(Pike_compiler->new_program, -  $3->current_file->str, -  $3->line_number); -  }else{ -  int i; -  struct identifier *id; -  int tmp=Pike_compiler->compiler_pass; -  i=isidentifier($4->u.sval.u.string); -  if(i<0) -  { -  /* Seriously broken... */ -  yyerror("Pass 2: program not defined!"); -  low_start_new_program(0, 2, 0, -  $1, -  &$<number>$); -  }else{ -  id=ID_FROM_INT(Pike_compiler->new_program, i); -  if(IDENTIFIER_IS_CONSTANT(id->identifier_flags)) -  { -  struct svalue *s; -  if ((id->func.offset >= 0) && -  ((s = &PROG_FROM_INT(Pike_compiler->new_program,i)-> -  constants[id->func.offset].sval)->type == T_PROGRAM)) -  { -  low_start_new_program(s->u.program, 2, -  $4->u.sval.u.string, -  $1, -  &$<number>$); -  -  /* fprintf(stderr, "Pass 2: Program %s has id %d\n", -  $4->u.sval.u.string->str, Pike_compiler->new_program->id); */ -  -  }else{ -  yyerror("Pass 2: constant redefined!"); -  low_start_new_program(0, 2, 0, -  $1, -  &$<number>$); -  } -  }else{ -  yyerror("Pass 2: class constant no longer constant!"); -  low_start_new_program(0, 2, 0, -  $1, -  &$<number>$); -  } -  } -  Pike_compiler->compiler_pass=tmp; -  } -  } -  { -  /* Clear scoped modifiers. */ -  $<number>$ = lex.pragmas; -  lex.pragmas &= ~ID_MODIFIER_MASK; -  } -  optional_create_arguments failsafe_program -  { -  struct program *p; +     if(Pike_compiler->compiler_pass == 1)    p=end_first_pass(0);    else