Branch: Tag:

2012-10-02

2012-10-02 10:07:44 by Per Hedbor <ph@opera.com>

Added a two new operators: "?->" and "?:"

?-> can be used to index something that is either indexable or null.
?: is an alias for ||

Very useful for things like:

C c = a && a->b && a->b->c;

which can now be rewritten as

C c = a?->b?->c;

The code in language.yacc also supports ?. and ?[], but there are
syntax conflicts with ?: for those:

?. conflicts with expr?.Module:...
?[] conflicts wtih expr?[softcast]:...

?: was added mostly to be compatible with other 'modern' C-like
languages.

97:   %token TOK_WHILE   %token TOK_XOR_EQ   %token TOK_OPTIONAL + %token TOK_SAFE_INDEX + %token TOK_SAFE_START_INDEX         %right '='   %right '?' -  +    %left TOK_LOR   %left TOK_LAND   %left '|'
3749:    COPY_LINE_NUMBER_INFO($$, $2);    free_node ($2);    } +  | expr4 TOK_SAFE_START_INDEX line_number_info expr0 ']' +  { +  /* A?[X] to ((tmp=A) && tmp[X]) */ +  if( $1->token == F_LOCAL ) +  { +  $$=mknode(F_LAND, $1, mknode(F_INDEX, $1, $4)); +  } +  else +  { +  fix_type_field( $1 ); +  if( $1->type ) +  { +  int temporary; +  $1->type->refs++; +  +  temporary = add_local_name(empty_pike_string, $1->type, 0); +  Pike_compiler->compiler_frame->variable[temporary].flags |= LOCAL_VAR_IS_USED; +  $$=mknode(F_LAND, +  mknode(F_ASSIGN, $1, mklocalnode(temporary,0)), +  mknode(F_INDEX, mklocalnode(temporary,0), $4)); +  } +  else +  { +  $$=mknode(F_INDEX, $1,$4); +  yyerror("Indexing unexpected value."); +  } +  } +  COPY_LINE_NUMBER_INFO($$, $3); +  free_node ($3); +  } +  | expr4 TOK_SAFE_START_INDEX line_number_info +  range_bound expected_dot_dot range_bound ']' +  { +  /* A?[X..Y] to ((tmp=A) && tmp[X..Y]) */ +  node *range = mknode(':',$4,$6); +  if( $1->token == F_LOCAL ) +  { +  $$ = mknode( F_LAND, $1, mknode(F_RANGE, $1, range) ); +  } +  else +  { +  fix_type_field( $1 ); +  if( $1->type ) +  { +  int temporary; +  $1->type->refs++; +  +  temporary = add_local_name(empty_pike_string, $1->type, 0); +  Pike_compiler->compiler_frame->variable[temporary].flags |= LOCAL_VAR_IS_USED; +  $$=mknode(F_LAND, +  mknode(F_ASSIGN, $1, mklocalnode(temporary,0) ), +  mknode(F_RANGE, mklocalnode(temporary,0), range) ); +  } +  else +  { +  $$ = mknode( F_LAND, $1, mknode(F_RANGE,$1,range) ); +  yyerror("Indexing unexpected value."); +  } +  } +  COPY_LINE_NUMBER_INFO($$, $3); +  free_node ($3); +  +  +  COPY_LINE_NUMBER_INFO($$, $3); +  free_node ($3); +  }    | expr4 open_bracket_with_line_info error ']'    {    $$=$1;
3832:    COPY_LINE_NUMBER_INFO($$, $3);    free_node ($3);    } +  | expr4 TOK_SAFE_INDEX line_number_info TOK_IDENTIFIER +  { +  /* A?->B to ((tmp=A) && tmp->B) */ +  int temporary; +  if( $1->token == F_LOCAL ) +  { +  $$=mknode(F_LAND, $1, mknode(F_ARROW, $1, $4)); +  } +  else +  { +  fix_type_field( $1 ); +  if( $1->type ) +  { +  $1->type->refs++; +  +  temporary = add_local_name(empty_pike_string, $1->type, 0); +  Pike_compiler->compiler_frame->variable[temporary].flags |= LOCAL_VAR_IS_USED; +  $$=mknode(F_LAND, +  mknode(F_ASSIGN, $1, mklocalnode(temporary,0)), +  mknode(F_ARROW, mklocalnode(temporary,0), $4)); +  } +  else +  { +  $$=mknode(F_ARROW, $1,$4); +  yyerror("Indexing unexpected value."); +  } +  } +  COPY_LINE_NUMBER_INFO($$, $3); +  free_node ($3); +  }    | expr4 '.' line_number_info TOK_IDENTIFIER    {    $$=index_node($1,".",$4->u.sval.u.string);