| Index: runtime/vm/parser.cc
 | 
| ===================================================================
 | 
| --- runtime/vm/parser.cc	(revision 12003)
 | 
| +++ runtime/vm/parser.cc	(working copy)
 | 
| @@ -143,34 +143,38 @@
 | 
|  
 | 
|  void ParsedFunction::AllocateVariables() {
 | 
|    LocalScope* scope = node_sequence()->scope();
 | 
| -  const int fixed_parameter_count = function().num_fixed_parameters();
 | 
| -  const int optional_parameter_count = function().num_optional_parameters();
 | 
| -  int parameter_count = fixed_parameter_count + optional_parameter_count;
 | 
| +  const intptr_t num_fixed_params = function().num_fixed_parameters();
 | 
| +  const intptr_t num_opt_pos_params =
 | 
| +      function().num_optional_positional_parameters();
 | 
| +  const intptr_t num_opt_named_params =
 | 
| +      function().num_optional_named_parameters();
 | 
| +  const intptr_t num_opt_params = num_opt_pos_params + num_opt_named_params;
 | 
| +  intptr_t num_params = num_fixed_params + num_opt_params;
 | 
|    const bool is_native_instance_closure =
 | 
|        function().is_native() && function().IsImplicitInstanceClosureFunction();
 | 
|    // Compute start indices to parameters and locals, and the number of
 | 
|    // parameters to copy.
 | 
| -  if ((optional_parameter_count == 0) && !is_native_instance_closure) {
 | 
| -    // Parameter i will be at fp[1 + parameter_count - i] and local variable
 | 
| +  if ((num_opt_params == 0) && !is_native_instance_closure) {
 | 
| +    // Parameter i will be at fp[1 + num_params - i] and local variable
 | 
|      // j will be at fp[kFirstLocalSlotIndex - j].
 | 
|      ASSERT(GetSavedArgumentsDescriptorVar() == NULL);
 | 
| -    first_parameter_index_ = 1 + parameter_count;
 | 
| +    first_parameter_index_ = 1 + num_params;
 | 
|      first_stack_local_index_ = kFirstLocalSlotIndex;
 | 
| -    copied_parameter_count_ = 0;
 | 
| +    num_copied_params_ = 0;
 | 
|    } else {
 | 
|      // Parameter i will be at fp[kFirstLocalSlotIndex - i] and local variable
 | 
| -    // j will be at fp[kFirstLocalSlotIndex - parameter_count - j].
 | 
| +    // j will be at fp[kFirstLocalSlotIndex - num_params - j].
 | 
|      // The saved argument descriptor variable must be allocated similarly to
 | 
|      // a parameter, so that it gets both a frame slot and a context slot when
 | 
|      // captured.
 | 
|      if (GetSavedArgumentsDescriptorVar() != NULL) {
 | 
| -      parameter_count += 1;
 | 
| +      num_params += 1;
 | 
|      }
 | 
|      first_parameter_index_ = kFirstLocalSlotIndex;
 | 
| -    first_stack_local_index_ = first_parameter_index_ - parameter_count;
 | 
| -    copied_parameter_count_ = parameter_count;
 | 
| +    first_stack_local_index_ = first_parameter_index_ - num_params;
 | 
| +    num_copied_params_ = num_params;
 | 
|      if (is_native_instance_closure) {
 | 
| -      copied_parameter_count_ += 1;
 | 
| +      num_copied_params_ += 1;
 | 
|        first_parameter_index_ -= 1;
 | 
|        first_stack_local_index_ -= 1;
 | 
|      }
 | 
| @@ -181,7 +185,7 @@
 | 
|    LocalScope* context_owner = NULL;  // No context needed yet.
 | 
|    int next_free_frame_index =
 | 
|        scope->AllocateVariables(first_parameter_index_,
 | 
| -                               parameter_count,
 | 
| +                               num_params,
 | 
|                                 first_stack_local_index_,
 | 
|                                 scope,
 | 
|                                 &context_owner);
 | 
| @@ -203,7 +207,7 @@
 | 
|  
 | 
|    // Frame indices are relative to the frame pointer and are decreasing.
 | 
|    ASSERT(next_free_frame_index <= first_stack_local_index_);
 | 
| -  stack_local_count_ = first_stack_local_index_ - next_free_frame_index;
 | 
| +  num_stack_locals_ = first_stack_local_index_ - next_free_frame_index;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -427,7 +431,8 @@
 | 
|    void Clear() {
 | 
|      num_fixed_parameters = 0;
 | 
|      num_optional_parameters = 0;
 | 
| -    has_named_optional_parameters = false;
 | 
| +    has_optional_positional_parameters = false;
 | 
| +    has_optional_named_parameters = false;
 | 
|      has_field_initializer = false;
 | 
|      implicitly_final = false;
 | 
|      this->parameters = new ZoneGrowableArray<ParamDesc>();
 | 
| @@ -458,7 +463,8 @@
 | 
|  
 | 
|    int num_fixed_parameters;
 | 
|    int num_optional_parameters;
 | 
| -  bool has_named_optional_parameters;  // Indicates use of the new syntax.
 | 
| +  bool has_optional_positional_parameters;
 | 
| +  bool has_optional_named_parameters;
 | 
|    bool has_field_initializer;
 | 
|    bool implicitly_final;
 | 
|    ZoneGrowableArray<ParamDesc>* parameters;
 | 
| @@ -773,7 +779,7 @@
 | 
|    TRACE_PARSER("ParseStaticConstGetter");
 | 
|    ParamList params;
 | 
|    ASSERT(func.num_fixed_parameters() == 0);  // static.
 | 
| -  ASSERT(func.num_optional_parameters() == 0);
 | 
| +  ASSERT(!func.HasOptionalParameters());
 | 
|    ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
 | 
|  
 | 
|    // Build local scope for function and populate with the formal parameters.
 | 
| @@ -889,7 +895,7 @@
 | 
|    ASSERT(current_class().raw() == func.Owner());
 | 
|    params.AddReceiver(ReceiverType(TokenPos()));
 | 
|    ASSERT(func.num_fixed_parameters() == 1);  // receiver.
 | 
| -  ASSERT(func.num_optional_parameters() == 0);
 | 
| +  ASSERT(!func.HasOptionalParameters());
 | 
|    ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
 | 
|  
 | 
|    // Build local scope for function and populate with the formal parameters.
 | 
| @@ -938,7 +944,7 @@
 | 
|                             &String::ZoneHandle(Symbols::Value()),
 | 
|                             &field_type);
 | 
|    ASSERT(func.num_fixed_parameters() == 2);  // receiver, value.
 | 
| -  ASSERT(func.num_optional_parameters() == 0);
 | 
| +  ASSERT(!func.HasOptionalParameters());
 | 
|    ASSERT(AbstractType::Handle(func.result_type()).IsVoidType());
 | 
|  
 | 
|    // Build local scope for function and populate with the formal parameters.
 | 
| @@ -1139,12 +1145,17 @@
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  if (CurrentToken() == Token::kASSIGN) {
 | 
| -    if (!params->has_named_optional_parameters ||
 | 
| +  if ((CurrentToken() == Token::kASSIGN) || (CurrentToken() == Token::kCOLON)) {
 | 
| +    if ((!params->has_optional_positional_parameters &&
 | 
| +         !params->has_optional_named_parameters) ||
 | 
|          !allow_explicit_default_value) {
 | 
|        ErrorMsg("parameter must not specify a default value");
 | 
|      }
 | 
| -    ConsumeToken();
 | 
| +    if (params->has_optional_positional_parameters) {
 | 
| +      ExpectToken(Token::kASSIGN);
 | 
| +    } else {
 | 
| +      ExpectToken(Token::kCOLON);
 | 
| +    }
 | 
|      params->num_optional_parameters++;
 | 
|      if (is_top_level_) {
 | 
|        // Skip default value parsing.
 | 
| @@ -1154,7 +1165,8 @@
 | 
|        parameter.default_value = &const_value;
 | 
|      }
 | 
|    } else {
 | 
| -    if (params->has_named_optional_parameters) {
 | 
| +    if (params->has_optional_positional_parameters ||
 | 
| +        params->has_optional_named_parameters) {
 | 
|        // Implicit default value is null.
 | 
|        params->num_optional_parameters++;
 | 
|        parameter.default_value = &Object::ZoneHandle();
 | 
| @@ -1176,18 +1188,26 @@
 | 
|    ASSERT(CurrentToken() == Token::kLPAREN);
 | 
|  
 | 
|    if (LookaheadToken(1) != Token::kRPAREN) {
 | 
| -    // Parse positional parameters.
 | 
| +    // Parse fixed parameters.
 | 
|      ParseFormalParameters(allow_explicit_default_values, params);
 | 
| -    if (params->has_named_optional_parameters) {
 | 
| -      // Parse named optional parameters.
 | 
| +    if (params->has_optional_positional_parameters ||
 | 
| +        params->has_optional_named_parameters) {
 | 
| +      // Parse optional parameters.
 | 
|        ParseFormalParameters(allow_explicit_default_values, params);
 | 
| -      if (CurrentToken() != Token::kRBRACK) {
 | 
| -        ErrorMsg("',' or ']' expected");
 | 
| +      if (params->has_optional_positional_parameters) {
 | 
| +        if (CurrentToken() != Token::kRBRACK) {
 | 
| +          ErrorMsg("',' or ']' expected");
 | 
| +        }
 | 
| +      } else {
 | 
| +        if (CurrentToken() != Token::kRBRACE) {
 | 
| +          ErrorMsg("',' or '}' expected");
 | 
| +        }
 | 
|        }
 | 
| -      ExpectToken(Token::kRBRACK);
 | 
| +      ConsumeToken();  // ']' or '}'.
 | 
|      }
 | 
|      if ((CurrentToken() != Token::kRPAREN) &&
 | 
| -        !params->has_named_optional_parameters) {
 | 
| +        !params->has_optional_positional_parameters &&
 | 
| +        !params->has_optional_named_parameters) {
 | 
|        ErrorMsg("',' or ')' expected");
 | 
|      }
 | 
|    } else {
 | 
| @@ -1197,18 +1217,26 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| -// Parses a sequence of normal or named formal parameters.
 | 
| +// Parses a sequence of normal or optional formal parameters.
 | 
|  void Parser::ParseFormalParameters(bool allow_explicit_default_values,
 | 
|                                     ParamList* params) {
 | 
|    TRACE_PARSER("ParseFormalParameters");
 | 
|    do {
 | 
|      ConsumeToken();
 | 
| -    if (!params->has_named_optional_parameters &&
 | 
| +    if (!params->has_optional_positional_parameters &&
 | 
| +        !params->has_optional_named_parameters &&
 | 
|          (CurrentToken() == Token::kLBRACK)) {
 | 
| -      // End of normal parameters, start of named parameters.
 | 
| -      params->has_named_optional_parameters = true;
 | 
| +      // End of normal parameters, start of optional positional parameters.
 | 
| +      params->has_optional_positional_parameters = true;
 | 
|        return;
 | 
|      }
 | 
| +    if (!params->has_optional_positional_parameters &&
 | 
| +        !params->has_optional_named_parameters &&
 | 
| +        (CurrentToken() == Token::kLBRACE)) {
 | 
| +      // End of normal parameters, start of optional named parameters.
 | 
| +      params->has_optional_named_parameters = true;
 | 
| +      return;
 | 
| +    }
 | 
|      ParseFormalParameter(allow_explicit_default_values, params);
 | 
|    } while (CurrentToken() == Token::kCOMMA);
 | 
|  }
 | 
| @@ -2748,7 +2776,8 @@
 | 
|      expected_num_parameters = 2;
 | 
|    }
 | 
|    if ((member.params.num_optional_parameters > 0) ||
 | 
| -      (member.params.has_named_optional_parameters) ||
 | 
| +      member.params.has_optional_positional_parameters ||
 | 
| +      member.params.has_optional_named_parameters ||
 | 
|        (member.params.num_fixed_parameters != expected_num_parameters)) {
 | 
|      // Subtract receiver when reporting number of expected arguments.
 | 
|      ErrorMsg(member.name_pos, "operator %s expects %"Pd" argument(s)",
 | 
| @@ -4279,8 +4308,12 @@
 | 
|  void Parser::AddFormalParamsToFunction(const ParamList* params,
 | 
|                                         const Function& func) {
 | 
|    ASSERT((params != NULL) && (params->parameters != NULL));
 | 
| -  func.set_num_fixed_parameters(params->num_fixed_parameters);
 | 
| -  func.set_num_optional_parameters(params->num_optional_parameters);
 | 
| +  ASSERT((params->num_optional_parameters > 0) ==
 | 
| +         (params->has_optional_positional_parameters ||
 | 
| +          params->has_optional_named_parameters));
 | 
| +  func.SetNumberOfParameters(params->num_fixed_parameters,
 | 
| +                             params->num_optional_parameters,
 | 
| +                             params->has_optional_positional_parameters);
 | 
|    const int num_parameters = params->parameters->length();
 | 
|    ASSERT(num_parameters == func.NumberOfParameters());
 | 
|    func.set_parameter_types(Array::Handle(Array::New(num_parameters,
 | 
| 
 |