Branch: Tag:

2004-10-30

2004-10-30 11:38:29 by Martin Stjernholm <mast@lysator.liu.se>

Implemented from-the-end indexing in ranges using the a[..<1] syntax. Added
`[..]. Still to do: Avoid fallback to `[] for ranges if it doesn't take two
args.

Rev: src/docode.c:1.181
Rev: src/interpret.c:1.358
Rev: src/interpret_functions.h:1.176
Rev: src/language.yacc:1.347
Rev: src/las.c:1.351
Rev: src/lexer.h:1.51
Rev: src/opcodes.h:1.41
Rev: src/operators.c:1.198
Rev: src/operators.h:1.16
Rev: src/pike_types.c:1.238
Rev: src/program.c:1.573
Rev: src/program.h:1.213
Rev: src/testsuite.in:1.741
Rev: src/treeopt.in:1.74

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.180 2004/10/28 20:13:47 mast Exp $ + || $Id: docode.c,v 1.181 2004/10/30 11:38:25 mast Exp $   */      #include "global.h"
593:    free_node(n);   }    + static void emit_range (node *n DO_IF_DEBUG (COMMA int num_args)) + { +  node *low = CADR (n), *high = CDDR (n); +  int bound_types; +  +  switch (low->token) { +  case F_RANGE_FROM_BEG: bound_types = RANGE_LOW_FROM_BEG; break; +  case F_RANGE_FROM_END: bound_types = RANGE_LOW_FROM_END; break; +  case F_RANGE_OPEN: bound_types = RANGE_LOW_OPEN; break; + #ifdef PIKE_DEBUG +  default: +  Pike_fatal ("Unexpected node %d as range lower bound.\n", low->token); + #endif +  } +  +  switch (high->token) { +  case F_RANGE_FROM_BEG: bound_types |= RANGE_HIGH_FROM_BEG; break; +  case F_RANGE_FROM_END: bound_types |= RANGE_HIGH_FROM_END; break; +  case F_RANGE_OPEN: bound_types |= RANGE_HIGH_OPEN; break; + #ifdef PIKE_DEBUG +  default: +  Pike_fatal ("Unexpected node %d as range upper bound.\n", high->token); + #endif +  } +  + #ifdef PIKE_DEBUG +  { +  int expected_args; +  switch (bound_types & (RANGE_LOW_OPEN|RANGE_HIGH_OPEN)) { +  case 0: +  expected_args = 2; break; +  case RANGE_LOW_OPEN: +  case RANGE_HIGH_OPEN: +  expected_args = 1; break; +  case RANGE_LOW_OPEN|RANGE_HIGH_OPEN: +  expected_args = 0; break; +  } +  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 int do_docode2(node *n, int flags)   {    ptrdiff_t tmp1,tmp2,tmp3;
936:    case F_MULTIPLY:    if(node_is_eq(CDR(n),CAAR(n)))    { +  int num_args;    tmp1=do_docode(CDR(n),DO_LVALUE);    if(match_types(CDR(n)->type, array_type_string) ||    match_types(CDR(n)->type, string_type_string) ||
943:    match_types(CDR(n)->type, multiset_type_string) ||    match_types(CDR(n)->type, mapping_type_string))    { -  switch(do_docode(check_node_hash(CDAR(n)), 0)) +  num_args = do_docode(check_node_hash(CDAR(n)), 0); +  switch (num_args)    { -  +  case 0: emit0(F_LTOSVAL1); break;    case 1: emit0(F_LTOSVAL2); break;    case 2: emit0(F_LTOSVAL3); break;   #ifdef PIKE_DEBUG
954:    }    }else{    emit0(F_LTOSVAL); -  do_docode(check_node_hash(CDAR(n)), 0); +  num_args = do_docode(check_node_hash(CDAR(n)), 0);    }    -  +  if (CAR (n)->token == F_RANGE) +  emit_range (CAR (n) DO_IF_DEBUG (COMMA num_args)); +  else    emit0(CAR(n)->token);       emit0(n->token);
1055:       case F_RANGE:    tmp1=do_docode(CAR(n),DO_NOT_COPY_TOPLEVEL); -  if(do_docode(CDR(n),DO_NOT_COPY)!=2) -  Pike_fatal("Compiler internal error (at %ld).\n",(long)lex.current_line); -  emit0(n->token); +  { + #ifdef PIKE_DEBUG +  int num_args = + #endif +  do_docode (CDR (n), DO_NOT_COPY); +  emit_range (n DO_IF_DEBUG (COMMA num_args));    return DO_NOT_WARN((INT32)tmp1); -  +  }    -  +  /* The special bound type nodes are simply ignored when the +  * arglist to the range operator is coded. emit_range looks at +  * them later on instead. */ +  case F_RANGE_FROM_BEG: +  case F_RANGE_FROM_END: +  return do_docode (CAR (n), flags); +  case F_RANGE_OPEN: +  return 0; +     case F_INC:    case F_POST_INC:    if(CAR(n)->token == F_AUTO_MAP_MARKER)
1278:    if(CAR(arr) && CAR(arr)->token==F_RANGE)    {    node *range = CAR(arr); -  node **a1=my_get_arg(&_CDR(range),0); -  node **a2=my_get_arg(&_CDR(range),1); -  if(a2[0]->token==F_CONSTANT && -  a2[0]->u.sval.type==T_INT && -  a2[0]->u.sval.u.integer==MAX_INT_TYPE && -  match_types (a1[0]->type, int_type_string)) +  node *low = CADR(range); +  node *high = CDDR(range); +  if(high->token == F_RANGE_OPEN && +  low->token == F_RANGE_FROM_BEG && +  match_types (low->type, int_type_string))    {    /* Optimize foreach(x[start..],y). */    do_docode (CAR(range), DO_NOT_COPY_TOPLEVEL);    do_docode (CDR(arr), DO_NOT_COPY|DO_LVALUE); -  do_docode (*a1, DO_NOT_COPY); +  do_docode (CAR(low), DO_NOT_COPY);    goto foreach_arg_pushed;    }    }
1567:       case F_ARG_LIST:    case F_COMMA_EXPR: +  case ':':    {    node *root = n;    node *parent = n->parent;