]>
Commit | Line | Data |
---|---|---|
7a938933 ILT |
1 | // parse.cc -- Go frontend parser. |
2 | ||
3 | // Copyright 2009 The Go Authors. All rights reserved. | |
4 | // Use of this source code is governed by a BSD-style | |
5 | // license that can be found in the LICENSE file. | |
6 | ||
7 | #include "go-system.h" | |
8 | ||
9 | #include "lex.h" | |
10 | #include "gogo.h" | |
11 | #include "types.h" | |
12 | #include "statements.h" | |
13 | #include "expressions.h" | |
14 | #include "parse.h" | |
15 | ||
16 | // Struct Parse::Enclosing_var_comparison. | |
17 | ||
18 | // Return true if v1 should be considered to be less than v2. | |
19 | ||
20 | bool | |
21 | Parse::Enclosing_var_comparison::operator()(const Enclosing_var& v1, | |
22 | const Enclosing_var& v2) | |
23 | { | |
24 | if (v1.var() == v2.var()) | |
25 | return false; | |
26 | ||
27 | const std::string& n1(v1.var()->name()); | |
28 | const std::string& n2(v2.var()->name()); | |
29 | int i = n1.compare(n2); | |
30 | if (i < 0) | |
31 | return true; | |
32 | else if (i > 0) | |
33 | return false; | |
34 | ||
35 | // If we get here it means that a single nested function refers to | |
36 | // two different variables defined in enclosing functions, and both | |
37 | // variables have the same name. I think this is impossible. | |
38 | gcc_unreachable(); | |
39 | } | |
40 | ||
41 | // Class Parse. | |
42 | ||
43 | Parse::Parse(Lex* lex, Gogo* gogo) | |
44 | : lex_(lex), | |
45 | token_(Token::make_invalid_token(0)), | |
46 | unget_token_(Token::make_invalid_token(0)), | |
47 | unget_token_valid_(false), | |
48 | gogo_(gogo), | |
bdc4349d ILT |
49 | break_stack_(NULL), |
50 | continue_stack_(NULL), | |
7a938933 ILT |
51 | iota_(0), |
52 | enclosing_vars_() | |
53 | { | |
54 | } | |
55 | ||
56 | // Return the current token. | |
57 | ||
58 | const Token* | |
59 | Parse::peek_token() | |
60 | { | |
61 | if (this->unget_token_valid_) | |
62 | return &this->unget_token_; | |
63 | if (this->token_.is_invalid()) | |
64 | this->token_ = this->lex_->next_token(); | |
65 | return &this->token_; | |
66 | } | |
67 | ||
68 | // Advance to the next token and return it. | |
69 | ||
70 | const Token* | |
71 | Parse::advance_token() | |
72 | { | |
73 | if (this->unget_token_valid_) | |
74 | { | |
75 | this->unget_token_valid_ = false; | |
76 | if (!this->token_.is_invalid()) | |
77 | return &this->token_; | |
78 | } | |
79 | this->token_ = this->lex_->next_token(); | |
80 | return &this->token_; | |
81 | } | |
82 | ||
83 | // Push a token back on the input stream. | |
84 | ||
85 | void | |
86 | Parse::unget_token(const Token& token) | |
87 | { | |
88 | gcc_assert(!this->unget_token_valid_); | |
89 | this->unget_token_ = token; | |
90 | this->unget_token_valid_ = true; | |
91 | } | |
92 | ||
93 | // The location of the current token. | |
94 | ||
95 | source_location | |
96 | Parse::location() | |
97 | { | |
98 | return this->peek_token()->location(); | |
99 | } | |
100 | ||
101 | // IdentifierList = identifier { "," identifier } . | |
102 | ||
103 | void | |
104 | Parse::identifier_list(Typed_identifier_list* til) | |
105 | { | |
106 | const Token* token = this->peek_token(); | |
107 | while (true) | |
108 | { | |
109 | if (!token->is_identifier()) | |
110 | { | |
111 | error_at(this->location(), "expected identifier"); | |
112 | return; | |
113 | } | |
114 | std::string name = | |
115 | this->gogo_->pack_hidden_name(token->identifier(), | |
116 | token->is_identifier_exported()); | |
117 | til->push_back(Typed_identifier(name, NULL, token->location())); | |
118 | token = this->advance_token(); | |
119 | if (!token->is_op(OPERATOR_COMMA)) | |
120 | return; | |
121 | token = this->advance_token(); | |
122 | } | |
123 | } | |
124 | ||
125 | // ExpressionList = Expression { "," Expression } . | |
126 | ||
127 | // If MAY_BE_SINK is true, the expressions in the list may be "_". | |
128 | ||
129 | Expression_list* | |
130 | Parse::expression_list(Expression* first, bool may_be_sink) | |
131 | { | |
132 | Expression_list* ret = new Expression_list(); | |
133 | if (first != NULL) | |
134 | ret->push_back(first); | |
135 | while (true) | |
136 | { | |
137 | ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink, true, | |
138 | NULL)); | |
139 | ||
140 | const Token* token = this->peek_token(); | |
141 | if (!token->is_op(OPERATOR_COMMA)) | |
142 | return ret; | |
143 | ||
144 | // Most expression lists permit a trailing comma. | |
145 | source_location location = token->location(); | |
146 | this->advance_token(); | |
147 | if (!this->expression_may_start_here()) | |
148 | { | |
149 | this->unget_token(Token::make_operator_token(OPERATOR_COMMA, | |
150 | location)); | |
151 | return ret; | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | // QualifiedIdent = [ PackageName "." ] identifier . | |
157 | // PackageName = identifier . | |
158 | ||
159 | // This sets *PNAME to the identifier and sets *PPACKAGE to the | |
160 | // package or NULL if there isn't one. This returns true on success, | |
161 | // false on failure in which case it will have emitted an error | |
162 | // message. | |
163 | ||
164 | bool | |
165 | Parse::qualified_ident(std::string* pname, Named_object** ppackage) | |
166 | { | |
167 | const Token* token = this->peek_token(); | |
168 | if (!token->is_identifier()) | |
169 | { | |
170 | error_at(this->location(), "expected identifier"); | |
171 | return false; | |
172 | } | |
173 | ||
174 | std::string name = token->identifier(); | |
175 | bool is_exported = token->is_identifier_exported(); | |
176 | name = this->gogo_->pack_hidden_name(name, is_exported); | |
177 | ||
178 | token = this->advance_token(); | |
179 | if (!token->is_op(OPERATOR_DOT)) | |
180 | { | |
181 | *pname = name; | |
182 | *ppackage = NULL; | |
183 | return true; | |
184 | } | |
185 | ||
186 | Named_object* package = this->gogo_->lookup(name, NULL); | |
187 | if (package == NULL || !package->is_package()) | |
188 | { | |
189 | error_at(this->location(), "expected package"); | |
190 | // We expect . IDENTIFIER; skip both. | |
191 | if (this->advance_token()->is_identifier()) | |
192 | this->advance_token(); | |
193 | return false; | |
194 | } | |
195 | ||
196 | package->package_value()->set_used(); | |
197 | ||
198 | token = this->advance_token(); | |
199 | if (!token->is_identifier()) | |
200 | { | |
201 | error_at(this->location(), "expected identifier"); | |
202 | return false; | |
203 | } | |
204 | ||
205 | name = token->identifier(); | |
206 | ||
207 | if (name == "_") | |
208 | { | |
209 | error_at(this->location(), "invalid use of %<_%>"); | |
210 | name = "blank"; | |
211 | } | |
212 | ||
213 | if (package->name() == this->gogo_->package_name()) | |
214 | name = this->gogo_->pack_hidden_name(name, | |
215 | token->is_identifier_exported()); | |
216 | ||
217 | *pname = name; | |
218 | *ppackage = package; | |
219 | ||
220 | this->advance_token(); | |
221 | ||
222 | return true; | |
223 | } | |
224 | ||
225 | // Type = TypeName | TypeLit | "(" Type ")" . | |
226 | // TypeLit = | |
227 | // ArrayType | StructType | PointerType | FunctionType | InterfaceType | | |
228 | // SliceType | MapType | ChannelType . | |
229 | ||
230 | Type* | |
231 | Parse::type() | |
232 | { | |
233 | const Token* token = this->peek_token(); | |
234 | if (token->is_identifier()) | |
235 | return this->type_name(true); | |
236 | else if (token->is_op(OPERATOR_LSQUARE)) | |
237 | return this->array_type(false); | |
238 | else if (token->is_keyword(KEYWORD_CHAN) | |
239 | || token->is_op(OPERATOR_CHANOP)) | |
240 | return this->channel_type(); | |
241 | else if (token->is_keyword(KEYWORD_INTERFACE)) | |
242 | return this->interface_type(); | |
243 | else if (token->is_keyword(KEYWORD_FUNC)) | |
244 | { | |
245 | source_location location = token->location(); | |
246 | this->advance_token(); | |
cad51bed ILT |
247 | Type* type = this->signature(NULL, location); |
248 | if (type == NULL) | |
249 | return Type::make_error_type(); | |
250 | return type; | |
7a938933 ILT |
251 | } |
252 | else if (token->is_keyword(KEYWORD_MAP)) | |
253 | return this->map_type(); | |
254 | else if (token->is_keyword(KEYWORD_STRUCT)) | |
255 | return this->struct_type(); | |
256 | else if (token->is_op(OPERATOR_MULT)) | |
257 | return this->pointer_type(); | |
258 | else if (token->is_op(OPERATOR_LPAREN)) | |
259 | { | |
260 | this->advance_token(); | |
261 | Type* ret = this->type(); | |
262 | if (this->peek_token()->is_op(OPERATOR_RPAREN)) | |
263 | this->advance_token(); | |
264 | else | |
265 | { | |
266 | if (!ret->is_error_type()) | |
267 | error_at(this->location(), "expected %<)%>"); | |
268 | } | |
269 | return ret; | |
270 | } | |
271 | else | |
272 | { | |
273 | error_at(token->location(), "expected type"); | |
274 | return Type::make_error_type(); | |
275 | } | |
276 | } | |
277 | ||
278 | bool | |
279 | Parse::type_may_start_here() | |
280 | { | |
281 | const Token* token = this->peek_token(); | |
282 | return (token->is_identifier() | |
283 | || token->is_op(OPERATOR_LSQUARE) | |
284 | || token->is_op(OPERATOR_CHANOP) | |
285 | || token->is_keyword(KEYWORD_CHAN) | |
286 | || token->is_keyword(KEYWORD_INTERFACE) | |
287 | || token->is_keyword(KEYWORD_FUNC) | |
288 | || token->is_keyword(KEYWORD_MAP) | |
289 | || token->is_keyword(KEYWORD_STRUCT) | |
290 | || token->is_op(OPERATOR_MULT) | |
291 | || token->is_op(OPERATOR_LPAREN)); | |
292 | } | |
293 | ||
294 | // TypeName = QualifiedIdent . | |
295 | ||
296 | // If MAY_BE_NIL is true, then an identifier with the value of the | |
297 | // predefined constant nil is accepted, returning the nil type. | |
298 | ||
299 | Type* | |
300 | Parse::type_name(bool issue_error) | |
301 | { | |
302 | source_location location = this->location(); | |
303 | ||
304 | std::string name; | |
305 | Named_object* package; | |
306 | if (!this->qualified_ident(&name, &package)) | |
307 | return Type::make_error_type(); | |
308 | ||
309 | Named_object* named_object; | |
310 | if (package == NULL) | |
311 | named_object = this->gogo_->lookup(name, NULL); | |
312 | else | |
313 | { | |
314 | named_object = package->package_value()->lookup(name); | |
315 | if (named_object == NULL | |
316 | && issue_error | |
317 | && package->name() != this->gogo_->package_name()) | |
318 | { | |
319 | // Check whether the name is there but hidden. | |
320 | std::string s = ('.' + package->package_value()->unique_prefix() | |
321 | + '.' + package->package_value()->name() | |
322 | + '.' + name); | |
323 | named_object = package->package_value()->lookup(s); | |
324 | if (named_object != NULL) | |
325 | { | |
326 | const std::string& packname(package->package_value()->name()); | |
327 | error_at(location, "invalid reference to hidden type %<%s.%s%>", | |
328 | Gogo::message_name(packname).c_str(), | |
329 | Gogo::message_name(name).c_str()); | |
330 | issue_error = false; | |
331 | } | |
332 | } | |
333 | } | |
334 | ||
335 | bool ok = true; | |
336 | if (named_object == NULL) | |
337 | { | |
338 | if (package != NULL) | |
339 | ok = false; | |
340 | else | |
341 | named_object = this->gogo_->add_unknown_name(name, location); | |
342 | } | |
343 | else if (named_object->is_type()) | |
344 | { | |
345 | if (!named_object->type_value()->is_visible()) | |
346 | ok = false; | |
347 | } | |
348 | else if (named_object->is_unknown() || named_object->is_type_declaration()) | |
349 | ; | |
350 | else | |
351 | ok = false; | |
352 | ||
353 | if (!ok) | |
354 | { | |
355 | if (issue_error) | |
356 | error_at(location, "expected type"); | |
357 | return Type::make_error_type(); | |
358 | } | |
359 | ||
360 | if (named_object->is_type()) | |
361 | return named_object->type_value(); | |
362 | else if (named_object->is_unknown() || named_object->is_type_declaration()) | |
363 | return Type::make_forward_declaration(named_object); | |
364 | else | |
365 | gcc_unreachable(); | |
366 | } | |
367 | ||
368 | // ArrayType = "[" [ ArrayLength ] "]" ElementType . | |
369 | // ArrayLength = Expression . | |
370 | // ElementType = CompleteType . | |
371 | ||
372 | Type* | |
373 | Parse::array_type(bool may_use_ellipsis) | |
374 | { | |
375 | gcc_assert(this->peek_token()->is_op(OPERATOR_LSQUARE)); | |
376 | const Token* token = this->advance_token(); | |
377 | ||
378 | Expression* length = NULL; | |
379 | if (token->is_op(OPERATOR_RSQUARE)) | |
380 | this->advance_token(); | |
381 | else | |
382 | { | |
383 | if (!token->is_op(OPERATOR_ELLIPSIS)) | |
384 | length = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
385 | else if (may_use_ellipsis) | |
386 | { | |
387 | // An ellipsis is used in composite literals to represent a | |
388 | // fixed array of the size of the number of elements. We | |
389 | // use a length of nil to represent this, and change the | |
390 | // length when parsing the composite literal. | |
391 | length = Expression::make_nil(this->location()); | |
392 | this->advance_token(); | |
393 | } | |
394 | else | |
395 | { | |
396 | error_at(this->location(), | |
397 | "use of %<[...]%> outside of array literal"); | |
398 | length = Expression::make_error(this->location()); | |
399 | this->advance_token(); | |
400 | } | |
401 | if (!this->peek_token()->is_op(OPERATOR_RSQUARE)) | |
402 | { | |
403 | error_at(this->location(), "expected %<]%>"); | |
404 | return Type::make_error_type(); | |
405 | } | |
406 | this->advance_token(); | |
407 | } | |
408 | ||
409 | Type* element_type = this->type(); | |
410 | ||
411 | return Type::make_array_type(element_type, length); | |
412 | } | |
413 | ||
414 | // MapType = "map" "[" KeyType "]" ValueType . | |
415 | // KeyType = CompleteType . | |
416 | // ValueType = CompleteType . | |
417 | ||
418 | Type* | |
419 | Parse::map_type() | |
420 | { | |
421 | source_location location = this->location(); | |
422 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_MAP)); | |
423 | if (!this->advance_token()->is_op(OPERATOR_LSQUARE)) | |
424 | { | |
425 | error_at(this->location(), "expected %<[%>"); | |
426 | return Type::make_error_type(); | |
427 | } | |
428 | this->advance_token(); | |
429 | ||
430 | Type* key_type = this->type(); | |
431 | ||
432 | if (!this->peek_token()->is_op(OPERATOR_RSQUARE)) | |
433 | { | |
434 | error_at(this->location(), "expected %<]%>"); | |
435 | return Type::make_error_type(); | |
436 | } | |
437 | this->advance_token(); | |
438 | ||
439 | Type* value_type = this->type(); | |
440 | ||
441 | if (key_type->is_error_type() || value_type->is_error_type()) | |
442 | return Type::make_error_type(); | |
443 | ||
444 | return Type::make_map_type(key_type, value_type, location); | |
445 | } | |
446 | ||
447 | // StructType = "struct" "{" { FieldDecl ";" } "}" . | |
448 | ||
449 | Type* | |
450 | Parse::struct_type() | |
451 | { | |
452 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_STRUCT)); | |
453 | source_location location = this->location(); | |
454 | if (!this->advance_token()->is_op(OPERATOR_LCURLY)) | |
455 | { | |
456 | source_location token_loc = this->location(); | |
457 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
458 | && this->advance_token()->is_op(OPERATOR_LCURLY)) | |
459 | error_at(token_loc, "unexpected semicolon or newline before %<{%>"); | |
460 | else | |
461 | { | |
462 | error_at(this->location(), "expected %<{%>"); | |
463 | return Type::make_error_type(); | |
464 | } | |
465 | } | |
466 | this->advance_token(); | |
467 | ||
468 | Struct_field_list* sfl = new Struct_field_list; | |
469 | while (!this->peek_token()->is_op(OPERATOR_RCURLY)) | |
470 | { | |
471 | this->field_decl(sfl); | |
472 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
473 | this->advance_token(); | |
474 | else if (!this->peek_token()->is_op(OPERATOR_RCURLY)) | |
475 | { | |
476 | error_at(this->location(), "expected %<;%> or %<}%> or newline"); | |
477 | if (!this->skip_past_error(OPERATOR_RCURLY)) | |
478 | return Type::make_error_type(); | |
479 | } | |
480 | } | |
481 | this->advance_token(); | |
482 | ||
483 | for (Struct_field_list::const_iterator pi = sfl->begin(); | |
484 | pi != sfl->end(); | |
485 | ++pi) | |
486 | { | |
487 | if (pi->type()->is_error_type()) | |
488 | return pi->type(); | |
489 | for (Struct_field_list::const_iterator pj = pi + 1; | |
490 | pj != sfl->end(); | |
491 | ++pj) | |
492 | { | |
493 | if (pi->field_name() == pj->field_name() | |
494 | && !Gogo::is_sink_name(pi->field_name())) | |
495 | error_at(pi->location(), "duplicate field name %<%s%>", | |
496 | Gogo::message_name(pi->field_name()).c_str()); | |
497 | } | |
498 | } | |
499 | ||
500 | return Type::make_struct_type(sfl, location); | |
501 | } | |
502 | ||
503 | // FieldDecl = (IdentifierList CompleteType | TypeName) [ Tag ] . | |
504 | // Tag = string_lit . | |
505 | ||
506 | void | |
507 | Parse::field_decl(Struct_field_list* sfl) | |
508 | { | |
509 | const Token* token = this->peek_token(); | |
510 | source_location location = token->location(); | |
511 | bool is_anonymous; | |
512 | bool is_anonymous_pointer; | |
513 | if (token->is_op(OPERATOR_MULT)) | |
514 | { | |
515 | is_anonymous = true; | |
516 | is_anonymous_pointer = true; | |
517 | } | |
518 | else if (token->is_identifier()) | |
519 | { | |
520 | std::string id = token->identifier(); | |
521 | bool is_id_exported = token->is_identifier_exported(); | |
522 | source_location id_location = token->location(); | |
523 | token = this->advance_token(); | |
524 | is_anonymous = (token->is_op(OPERATOR_SEMICOLON) | |
525 | || token->is_op(OPERATOR_RCURLY) | |
526 | || token->is_op(OPERATOR_DOT) | |
527 | || token->is_string()); | |
528 | is_anonymous_pointer = false; | |
529 | this->unget_token(Token::make_identifier_token(id, is_id_exported, | |
530 | id_location)); | |
531 | } | |
532 | else | |
533 | { | |
534 | error_at(this->location(), "expected field name"); | |
535 | while (!token->is_op(OPERATOR_SEMICOLON) | |
536 | && !token->is_op(OPERATOR_RCURLY) | |
537 | && !token->is_eof()) | |
538 | token = this->advance_token(); | |
539 | return; | |
540 | } | |
541 | ||
542 | if (is_anonymous) | |
543 | { | |
544 | if (is_anonymous_pointer) | |
545 | { | |
546 | this->advance_token(); | |
547 | if (!this->peek_token()->is_identifier()) | |
548 | { | |
549 | error_at(this->location(), "expected field name"); | |
550 | while (!token->is_op(OPERATOR_SEMICOLON) | |
551 | && !token->is_op(OPERATOR_RCURLY) | |
552 | && !token->is_eof()) | |
553 | token = this->advance_token(); | |
554 | return; | |
555 | } | |
556 | } | |
557 | Type* type = this->type_name(true); | |
558 | ||
559 | std::string tag; | |
560 | if (this->peek_token()->is_string()) | |
561 | { | |
562 | tag = this->peek_token()->string_value(); | |
563 | this->advance_token(); | |
564 | } | |
565 | ||
566 | if (!type->is_error_type()) | |
567 | { | |
568 | if (is_anonymous_pointer) | |
569 | type = Type::make_pointer_type(type); | |
570 | sfl->push_back(Struct_field(Typed_identifier("", type, location))); | |
571 | if (!tag.empty()) | |
572 | sfl->back().set_tag(tag); | |
573 | } | |
574 | } | |
575 | else | |
576 | { | |
577 | Typed_identifier_list til; | |
578 | while (true) | |
579 | { | |
580 | token = this->peek_token(); | |
581 | if (!token->is_identifier()) | |
582 | { | |
583 | error_at(this->location(), "expected identifier"); | |
584 | return; | |
585 | } | |
586 | std::string name = | |
587 | this->gogo_->pack_hidden_name(token->identifier(), | |
588 | token->is_identifier_exported()); | |
589 | til.push_back(Typed_identifier(name, NULL, token->location())); | |
590 | if (!this->advance_token()->is_op(OPERATOR_COMMA)) | |
591 | break; | |
592 | this->advance_token(); | |
593 | } | |
594 | ||
595 | Type* type = this->type(); | |
596 | ||
597 | std::string tag; | |
598 | if (this->peek_token()->is_string()) | |
599 | { | |
600 | tag = this->peek_token()->string_value(); | |
601 | this->advance_token(); | |
602 | } | |
603 | ||
604 | for (Typed_identifier_list::iterator p = til.begin(); | |
605 | p != til.end(); | |
606 | ++p) | |
607 | { | |
608 | p->set_type(type); | |
609 | sfl->push_back(Struct_field(*p)); | |
610 | if (!tag.empty()) | |
611 | sfl->back().set_tag(tag); | |
612 | } | |
613 | } | |
614 | } | |
615 | ||
616 | // PointerType = "*" Type . | |
617 | ||
618 | Type* | |
619 | Parse::pointer_type() | |
620 | { | |
621 | gcc_assert(this->peek_token()->is_op(OPERATOR_MULT)); | |
622 | this->advance_token(); | |
623 | Type* type = this->type(); | |
624 | if (type->is_error_type()) | |
625 | return type; | |
626 | return Type::make_pointer_type(type); | |
627 | } | |
628 | ||
629 | // ChannelType = Channel | SendChannel | RecvChannel . | |
630 | // Channel = "chan" ElementType . | |
631 | // SendChannel = "chan" "<-" ElementType . | |
632 | // RecvChannel = "<-" "chan" ElementType . | |
633 | ||
634 | Type* | |
635 | Parse::channel_type() | |
636 | { | |
637 | const Token* token = this->peek_token(); | |
638 | bool send = true; | |
639 | bool receive = true; | |
640 | if (token->is_op(OPERATOR_CHANOP)) | |
641 | { | |
642 | if (!this->advance_token()->is_keyword(KEYWORD_CHAN)) | |
643 | { | |
644 | error_at(this->location(), "expected %<chan%>"); | |
645 | return Type::make_error_type(); | |
646 | } | |
647 | send = false; | |
648 | this->advance_token(); | |
649 | } | |
650 | else | |
651 | { | |
652 | gcc_assert(token->is_keyword(KEYWORD_CHAN)); | |
653 | if (this->advance_token()->is_op(OPERATOR_CHANOP)) | |
654 | { | |
655 | receive = false; | |
656 | this->advance_token(); | |
657 | } | |
658 | } | |
659 | Type* element_type = this->type(); | |
660 | return Type::make_channel_type(send, receive, element_type); | |
661 | } | |
662 | ||
663 | // Signature = Parameters [ Result ] . | |
664 | ||
665 | // RECEIVER is the receiver if there is one, or NULL. LOCATION is the | |
666 | // location of the start of the type. | |
667 | ||
cad51bed ILT |
668 | // This returns NULL on a parse error. |
669 | ||
7a938933 ILT |
670 | Function_type* |
671 | Parse::signature(Typed_identifier* receiver, source_location location) | |
672 | { | |
673 | bool is_varargs = false; | |
cad51bed ILT |
674 | Typed_identifier_list* params; |
675 | bool params_ok = this->parameters(¶ms, &is_varargs); | |
7a938933 ILT |
676 | |
677 | Typed_identifier_list* result = NULL; | |
678 | if (this->peek_token()->is_op(OPERATOR_LPAREN) | |
679 | || this->type_may_start_here()) | |
cad51bed ILT |
680 | { |
681 | if (!this->result(&result)) | |
682 | return NULL; | |
683 | } | |
684 | ||
685 | if (!params_ok) | |
686 | return NULL; | |
7a938933 ILT |
687 | |
688 | Function_type* ret = Type::make_function_type(receiver, params, result, | |
689 | location); | |
690 | if (is_varargs) | |
691 | ret->set_is_varargs(); | |
692 | return ret; | |
693 | } | |
694 | ||
695 | // Parameters = "(" [ ParameterList [ "," ] ] ")" . | |
696 | ||
cad51bed ILT |
697 | // This returns false on a parse error. |
698 | ||
699 | bool | |
700 | Parse::parameters(Typed_identifier_list** pparams, bool* is_varargs) | |
7a938933 | 701 | { |
cad51bed ILT |
702 | *pparams = NULL; |
703 | ||
7a938933 ILT |
704 | if (!this->peek_token()->is_op(OPERATOR_LPAREN)) |
705 | { | |
706 | error_at(this->location(), "expected %<(%>"); | |
cad51bed | 707 | return false; |
7a938933 ILT |
708 | } |
709 | ||
710 | Typed_identifier_list* params = NULL; | |
cad51bed | 711 | bool saw_error = false; |
7a938933 ILT |
712 | |
713 | const Token* token = this->advance_token(); | |
714 | if (!token->is_op(OPERATOR_RPAREN)) | |
715 | { | |
716 | params = this->parameter_list(is_varargs); | |
cad51bed ILT |
717 | if (params == NULL) |
718 | saw_error = true; | |
7a938933 ILT |
719 | token = this->peek_token(); |
720 | } | |
721 | ||
722 | // The optional trailing comma is picked up in parameter_list. | |
723 | ||
724 | if (!token->is_op(OPERATOR_RPAREN)) | |
725 | error_at(this->location(), "expected %<)%>"); | |
726 | else | |
727 | this->advance_token(); | |
728 | ||
cad51bed ILT |
729 | if (saw_error) |
730 | return false; | |
731 | ||
732 | *pparams = params; | |
733 | return true; | |
7a938933 ILT |
734 | } |
735 | ||
736 | // ParameterList = ParameterDecl { "," ParameterDecl } . | |
737 | ||
738 | // This sets *IS_VARARGS if the list ends with an ellipsis. | |
739 | // IS_VARARGS will be NULL if varargs are not permitted. | |
740 | ||
741 | // We pick up an optional trailing comma. | |
742 | ||
cad51bed ILT |
743 | // This returns NULL if some error is seen. |
744 | ||
7a938933 ILT |
745 | Typed_identifier_list* |
746 | Parse::parameter_list(bool* is_varargs) | |
747 | { | |
748 | source_location location = this->location(); | |
749 | Typed_identifier_list* ret = new Typed_identifier_list(); | |
750 | ||
cad51bed ILT |
751 | bool saw_error = false; |
752 | ||
7a938933 ILT |
753 | // If we see an identifier and then a comma, then we don't know |
754 | // whether we are looking at a list of identifiers followed by a | |
755 | // type, or a list of types given by name. We have to do an | |
756 | // arbitrary lookahead to figure it out. | |
757 | ||
758 | bool parameters_have_names; | |
759 | const Token* token = this->peek_token(); | |
760 | if (!token->is_identifier()) | |
761 | { | |
762 | // This must be a type which starts with something like '*'. | |
763 | parameters_have_names = false; | |
764 | } | |
765 | else | |
766 | { | |
767 | std::string name = token->identifier(); | |
768 | bool is_exported = token->is_identifier_exported(); | |
769 | source_location location = token->location(); | |
770 | token = this->advance_token(); | |
771 | if (!token->is_op(OPERATOR_COMMA)) | |
772 | { | |
773 | if (token->is_op(OPERATOR_DOT)) | |
774 | { | |
775 | // This is a qualified identifier, which must turn out | |
776 | // to be a type. | |
777 | parameters_have_names = false; | |
778 | } | |
779 | else if (token->is_op(OPERATOR_RPAREN)) | |
780 | { | |
781 | // A single identifier followed by a parenthesis must be | |
782 | // a type name. | |
783 | parameters_have_names = false; | |
784 | } | |
785 | else | |
786 | { | |
787 | // An identifier followed by something other than a | |
788 | // comma or a dot or a right parenthesis must be a | |
789 | // parameter name followed by a type. | |
790 | parameters_have_names = true; | |
791 | } | |
792 | ||
793 | this->unget_token(Token::make_identifier_token(name, is_exported, | |
794 | location)); | |
795 | } | |
796 | else | |
797 | { | |
798 | // An identifier followed by a comma may be the first in a | |
799 | // list of parameter names followed by a type, or it may be | |
800 | // the first in a list of types without parameter names. To | |
801 | // find out we gather as many identifiers separated by | |
802 | // commas as we can. | |
803 | std::string id_name = this->gogo_->pack_hidden_name(name, | |
804 | is_exported); | |
805 | ret->push_back(Typed_identifier(id_name, NULL, location)); | |
806 | bool just_saw_comma = true; | |
807 | while (this->advance_token()->is_identifier()) | |
808 | { | |
809 | name = this->peek_token()->identifier(); | |
810 | is_exported = this->peek_token()->is_identifier_exported(); | |
811 | location = this->peek_token()->location(); | |
812 | id_name = this->gogo_->pack_hidden_name(name, is_exported); | |
813 | ret->push_back(Typed_identifier(id_name, NULL, location)); | |
814 | if (!this->advance_token()->is_op(OPERATOR_COMMA)) | |
815 | { | |
816 | just_saw_comma = false; | |
817 | break; | |
818 | } | |
819 | } | |
820 | ||
821 | if (just_saw_comma) | |
822 | { | |
823 | // We saw ID1 "," ID2 "," followed by something which | |
824 | // was not an identifier. We must be seeing the start | |
825 | // of a type, and ID1 and ID2 must be types, and the | |
826 | // parameters don't have names. | |
827 | parameters_have_names = false; | |
828 | } | |
829 | else if (this->peek_token()->is_op(OPERATOR_RPAREN)) | |
830 | { | |
831 | // We saw ID1 "," ID2 ")". ID1 and ID2 must be types, | |
832 | // and the parameters don't have names. | |
833 | parameters_have_names = false; | |
834 | } | |
835 | else if (this->peek_token()->is_op(OPERATOR_DOT)) | |
836 | { | |
837 | // We saw ID1 "," ID2 ".". ID2 must be a package name, | |
838 | // ID1 must be a type, and the parameters don't have | |
839 | // names. | |
840 | parameters_have_names = false; | |
841 | this->unget_token(Token::make_identifier_token(name, is_exported, | |
842 | location)); | |
843 | ret->pop_back(); | |
844 | just_saw_comma = true; | |
845 | } | |
846 | else | |
847 | { | |
848 | // We saw ID1 "," ID2 followed by something other than | |
849 | // ",", ".", or ")". We must be looking at the start of | |
850 | // a type, and ID1 and ID2 must be parameter names. | |
851 | parameters_have_names = true; | |
852 | } | |
853 | ||
854 | if (parameters_have_names) | |
855 | { | |
856 | gcc_assert(!just_saw_comma); | |
857 | // We have just seen ID1, ID2 xxx. | |
858 | Type* type; | |
859 | if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS)) | |
860 | type = this->type(); | |
861 | else | |
862 | { | |
863 | error_at(this->location(), "%<...%> only permits one name"); | |
cad51bed | 864 | saw_error = true; |
7a938933 ILT |
865 | this->advance_token(); |
866 | type = this->type(); | |
867 | } | |
868 | for (size_t i = 0; i < ret->size(); ++i) | |
869 | ret->set_type(i, type); | |
870 | if (!this->peek_token()->is_op(OPERATOR_COMMA)) | |
cad51bed | 871 | return saw_error ? NULL : ret; |
7a938933 | 872 | if (this->advance_token()->is_op(OPERATOR_RPAREN)) |
cad51bed | 873 | return saw_error ? NULL : ret; |
7a938933 ILT |
874 | } |
875 | else | |
876 | { | |
877 | Typed_identifier_list* tret = new Typed_identifier_list(); | |
878 | for (Typed_identifier_list::const_iterator p = ret->begin(); | |
879 | p != ret->end(); | |
880 | ++p) | |
881 | { | |
882 | Named_object* no = this->gogo_->lookup(p->name(), NULL); | |
883 | Type* type; | |
884 | if (no == NULL) | |
885 | no = this->gogo_->add_unknown_name(p->name(), | |
886 | p->location()); | |
887 | ||
888 | if (no->is_type()) | |
889 | type = no->type_value(); | |
890 | else if (no->is_unknown() || no->is_type_declaration()) | |
891 | type = Type::make_forward_declaration(no); | |
892 | else | |
893 | { | |
894 | error_at(p->location(), "expected %<%s%> to be a type", | |
895 | Gogo::message_name(p->name()).c_str()); | |
cad51bed | 896 | saw_error = true; |
7a938933 ILT |
897 | type = Type::make_error_type(); |
898 | } | |
899 | tret->push_back(Typed_identifier("", type, p->location())); | |
900 | } | |
901 | delete ret; | |
902 | ret = tret; | |
903 | if (!just_saw_comma | |
904 | || this->peek_token()->is_op(OPERATOR_RPAREN)) | |
cad51bed | 905 | return saw_error ? NULL : ret; |
7a938933 ILT |
906 | } |
907 | } | |
908 | } | |
909 | ||
910 | bool mix_error = false; | |
911 | this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error); | |
912 | while (this->peek_token()->is_op(OPERATOR_COMMA)) | |
913 | { | |
914 | if (is_varargs != NULL && *is_varargs) | |
cad51bed ILT |
915 | { |
916 | error_at(this->location(), "%<...%> must be last parameter"); | |
917 | saw_error = true; | |
918 | } | |
7a938933 ILT |
919 | if (this->advance_token()->is_op(OPERATOR_RPAREN)) |
920 | break; | |
921 | this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error); | |
922 | } | |
923 | if (mix_error) | |
cad51bed ILT |
924 | { |
925 | error_at(location, "invalid named/anonymous mix"); | |
926 | saw_error = true; | |
927 | } | |
928 | if (saw_error) | |
929 | { | |
930 | delete ret; | |
931 | return NULL; | |
932 | } | |
7a938933 ILT |
933 | return ret; |
934 | } | |
935 | ||
936 | // ParameterDecl = [ IdentifierList ] [ "..." ] Type . | |
937 | ||
938 | void | |
939 | Parse::parameter_decl(bool parameters_have_names, | |
940 | Typed_identifier_list* til, | |
941 | bool* is_varargs, | |
942 | bool* mix_error) | |
943 | { | |
944 | if (!parameters_have_names) | |
945 | { | |
946 | Type* type; | |
947 | source_location location = this->location(); | |
948 | if (!this->peek_token()->is_identifier()) | |
949 | { | |
950 | if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS)) | |
951 | type = this->type(); | |
952 | else | |
953 | { | |
954 | if (is_varargs == NULL) | |
955 | error_at(this->location(), "invalid use of %<...%>"); | |
956 | else | |
957 | *is_varargs = true; | |
958 | this->advance_token(); | |
959 | if (is_varargs == NULL | |
960 | && this->peek_token()->is_op(OPERATOR_RPAREN)) | |
961 | type = Type::make_error_type(); | |
962 | else | |
963 | { | |
964 | Type* element_type = this->type(); | |
965 | type = Type::make_array_type(element_type, NULL); | |
966 | } | |
967 | } | |
968 | } | |
969 | else | |
970 | { | |
971 | type = this->type_name(false); | |
972 | if (type->is_error_type() | |
973 | || (!this->peek_token()->is_op(OPERATOR_COMMA) | |
974 | && !this->peek_token()->is_op(OPERATOR_RPAREN))) | |
975 | { | |
976 | *mix_error = true; | |
977 | while (!this->peek_token()->is_op(OPERATOR_COMMA) | |
978 | && !this->peek_token()->is_op(OPERATOR_RPAREN)) | |
979 | this->advance_token(); | |
980 | } | |
981 | } | |
982 | if (!type->is_error_type()) | |
983 | til->push_back(Typed_identifier("", type, location)); | |
984 | } | |
985 | else | |
986 | { | |
987 | size_t orig_count = til->size(); | |
988 | if (this->peek_token()->is_identifier()) | |
989 | this->identifier_list(til); | |
990 | else | |
991 | *mix_error = true; | |
992 | size_t new_count = til->size(); | |
993 | ||
994 | Type* type; | |
995 | if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS)) | |
996 | type = this->type(); | |
997 | else | |
998 | { | |
999 | if (is_varargs == NULL) | |
1000 | error_at(this->location(), "invalid use of %<...%>"); | |
1001 | else if (new_count > orig_count + 1) | |
1002 | error_at(this->location(), "%<...%> only permits one name"); | |
1003 | else | |
1004 | *is_varargs = true; | |
1005 | this->advance_token(); | |
1006 | Type* element_type = this->type(); | |
1007 | type = Type::make_array_type(element_type, NULL); | |
1008 | } | |
1009 | for (size_t i = orig_count; i < new_count; ++i) | |
1010 | til->set_type(i, type); | |
1011 | } | |
1012 | } | |
1013 | ||
1014 | // Result = Parameters | Type . | |
1015 | ||
cad51bed ILT |
1016 | // This returns false on a parse error. |
1017 | ||
1018 | bool | |
1019 | Parse::result(Typed_identifier_list** presults) | |
7a938933 ILT |
1020 | { |
1021 | if (this->peek_token()->is_op(OPERATOR_LPAREN)) | |
cad51bed | 1022 | return this->parameters(presults, NULL); |
7a938933 ILT |
1023 | else |
1024 | { | |
1025 | source_location location = this->location(); | |
7a938933 | 1026 | Type* type = this->type(); |
cad51bed ILT |
1027 | if (type->is_error_type()) |
1028 | { | |
1029 | *presults = NULL; | |
1030 | return false; | |
1031 | } | |
1032 | Typed_identifier_list* til = new Typed_identifier_list(); | |
7a938933 | 1033 | til->push_back(Typed_identifier("", type, location)); |
cad51bed ILT |
1034 | *presults = til; |
1035 | return true; | |
7a938933 ILT |
1036 | } |
1037 | } | |
1038 | ||
1039 | // Block = "{" [ StatementList ] "}" . | |
1040 | ||
1041 | // Returns the location of the closing brace. | |
1042 | ||
1043 | source_location | |
1044 | Parse::block() | |
1045 | { | |
1046 | if (!this->peek_token()->is_op(OPERATOR_LCURLY)) | |
1047 | { | |
1048 | source_location loc = this->location(); | |
1049 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
1050 | && this->advance_token()->is_op(OPERATOR_LCURLY)) | |
1051 | error_at(loc, "unexpected semicolon or newline before %<{%>"); | |
1052 | else | |
1053 | { | |
1054 | error_at(this->location(), "expected %<{%>"); | |
1055 | return UNKNOWN_LOCATION; | |
1056 | } | |
1057 | } | |
1058 | ||
1059 | const Token* token = this->advance_token(); | |
1060 | ||
1061 | if (!token->is_op(OPERATOR_RCURLY)) | |
1062 | { | |
1063 | this->statement_list(); | |
1064 | token = this->peek_token(); | |
1065 | if (!token->is_op(OPERATOR_RCURLY)) | |
1066 | { | |
1067 | if (!token->is_eof() || !saw_errors()) | |
1068 | error_at(this->location(), "expected %<}%>"); | |
1069 | ||
1070 | // Skip ahead to the end of the block, in hopes of avoiding | |
1071 | // lots of meaningless errors. | |
1072 | source_location ret = token->location(); | |
1073 | int nest = 0; | |
1074 | while (!token->is_eof()) | |
1075 | { | |
1076 | if (token->is_op(OPERATOR_LCURLY)) | |
1077 | ++nest; | |
1078 | else if (token->is_op(OPERATOR_RCURLY)) | |
1079 | { | |
1080 | --nest; | |
1081 | if (nest < 0) | |
1082 | { | |
1083 | this->advance_token(); | |
1084 | break; | |
1085 | } | |
1086 | } | |
1087 | token = this->advance_token(); | |
1088 | ret = token->location(); | |
1089 | } | |
1090 | return ret; | |
1091 | } | |
1092 | } | |
1093 | ||
1094 | source_location ret = token->location(); | |
1095 | this->advance_token(); | |
1096 | return ret; | |
1097 | } | |
1098 | ||
1099 | // InterfaceType = "interface" "{" [ MethodSpecList ] "}" . | |
1100 | // MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] . | |
1101 | ||
1102 | Type* | |
1103 | Parse::interface_type() | |
1104 | { | |
1105 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_INTERFACE)); | |
1106 | source_location location = this->location(); | |
1107 | ||
1108 | if (!this->advance_token()->is_op(OPERATOR_LCURLY)) | |
1109 | { | |
1110 | source_location token_loc = this->location(); | |
1111 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
1112 | && this->advance_token()->is_op(OPERATOR_LCURLY)) | |
1113 | error_at(token_loc, "unexpected semicolon or newline before %<{%>"); | |
1114 | else | |
1115 | { | |
1116 | error_at(this->location(), "expected %<{%>"); | |
1117 | return Type::make_error_type(); | |
1118 | } | |
1119 | } | |
1120 | this->advance_token(); | |
1121 | ||
1122 | Typed_identifier_list* methods = new Typed_identifier_list(); | |
1123 | if (!this->peek_token()->is_op(OPERATOR_RCURLY)) | |
1124 | { | |
1125 | this->method_spec(methods); | |
1126 | while (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
1127 | { | |
1128 | if (this->advance_token()->is_op(OPERATOR_RCURLY)) | |
1129 | break; | |
1130 | this->method_spec(methods); | |
1131 | } | |
1132 | if (!this->peek_token()->is_op(OPERATOR_RCURLY)) | |
1133 | { | |
1134 | error_at(this->location(), "expected %<}%>"); | |
1135 | while (!this->advance_token()->is_op(OPERATOR_RCURLY)) | |
1136 | { | |
1137 | if (this->peek_token()->is_eof()) | |
1138 | return Type::make_error_type(); | |
1139 | } | |
1140 | } | |
1141 | } | |
1142 | this->advance_token(); | |
1143 | ||
1144 | if (methods->empty()) | |
1145 | { | |
1146 | delete methods; | |
1147 | methods = NULL; | |
1148 | } | |
1149 | ||
1150 | Interface_type* ret = Type::make_interface_type(methods, location); | |
1151 | this->gogo_->record_interface_type(ret); | |
1152 | return ret; | |
1153 | } | |
1154 | ||
1155 | // MethodSpec = MethodName Signature | InterfaceTypeName . | |
1156 | // MethodName = identifier . | |
1157 | // InterfaceTypeName = TypeName . | |
1158 | ||
cad51bed | 1159 | void |
7a938933 ILT |
1160 | Parse::method_spec(Typed_identifier_list* methods) |
1161 | { | |
1162 | const Token* token = this->peek_token(); | |
1163 | if (!token->is_identifier()) | |
1164 | { | |
1165 | error_at(this->location(), "expected identifier"); | |
cad51bed | 1166 | return; |
7a938933 ILT |
1167 | } |
1168 | ||
1169 | std::string name = token->identifier(); | |
1170 | bool is_exported = token->is_identifier_exported(); | |
1171 | source_location location = token->location(); | |
1172 | ||
1173 | if (this->advance_token()->is_op(OPERATOR_LPAREN)) | |
1174 | { | |
1175 | // This is a MethodName. | |
1176 | name = this->gogo_->pack_hidden_name(name, is_exported); | |
cad51bed ILT |
1177 | Type* type = this->signature(NULL, location); |
1178 | if (type == NULL) | |
1179 | return; | |
7a938933 ILT |
1180 | methods->push_back(Typed_identifier(name, type, location)); |
1181 | } | |
1182 | else | |
1183 | { | |
1184 | this->unget_token(Token::make_identifier_token(name, is_exported, | |
1185 | location)); | |
1186 | Type* type = this->type_name(false); | |
1187 | if (type->is_error_type() | |
1188 | || (!this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
1189 | && !this->peek_token()->is_op(OPERATOR_RCURLY))) | |
1190 | { | |
1191 | if (this->peek_token()->is_op(OPERATOR_COMMA)) | |
1192 | error_at(this->location(), | |
1193 | "name list not allowed in interface type"); | |
1194 | else | |
1195 | error_at(location, "expected signature or type name"); | |
1196 | token = this->peek_token(); | |
1197 | while (!token->is_eof() | |
1198 | && !token->is_op(OPERATOR_SEMICOLON) | |
1199 | && !token->is_op(OPERATOR_RCURLY)) | |
1200 | token = this->advance_token(); | |
cad51bed | 1201 | return; |
7a938933 ILT |
1202 | } |
1203 | // This must be an interface type, but we can't check that now. | |
1204 | // We check it and pull out the methods in | |
1205 | // Interface_type::do_verify. | |
1206 | methods->push_back(Typed_identifier("", type, location)); | |
1207 | } | |
7a938933 ILT |
1208 | } |
1209 | ||
1210 | // Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl . | |
1211 | ||
1212 | void | |
1213 | Parse::declaration() | |
1214 | { | |
1215 | const Token* token = this->peek_token(); | |
1216 | if (token->is_keyword(KEYWORD_CONST)) | |
1217 | this->const_decl(); | |
1218 | else if (token->is_keyword(KEYWORD_TYPE)) | |
1219 | this->type_decl(); | |
1220 | else if (token->is_keyword(KEYWORD_VAR)) | |
1221 | this->var_decl(); | |
1222 | else if (token->is_keyword(KEYWORD_FUNC)) | |
1223 | this->function_decl(); | |
1224 | else | |
1225 | { | |
1226 | error_at(this->location(), "expected declaration"); | |
1227 | this->advance_token(); | |
1228 | } | |
1229 | } | |
1230 | ||
1231 | bool | |
1232 | Parse::declaration_may_start_here() | |
1233 | { | |
1234 | const Token* token = this->peek_token(); | |
1235 | return (token->is_keyword(KEYWORD_CONST) | |
1236 | || token->is_keyword(KEYWORD_TYPE) | |
1237 | || token->is_keyword(KEYWORD_VAR) | |
1238 | || token->is_keyword(KEYWORD_FUNC)); | |
1239 | } | |
1240 | ||
1241 | // Decl<P> = P | "(" [ List<P> ] ")" . | |
1242 | ||
1243 | void | |
1244 | Parse::decl(void (Parse::*pfn)(void*), void* varg) | |
1245 | { | |
1246 | if (!this->peek_token()->is_op(OPERATOR_LPAREN)) | |
1247 | (this->*pfn)(varg); | |
1248 | else | |
1249 | { | |
1250 | if (!this->advance_token()->is_op(OPERATOR_RPAREN)) | |
1251 | { | |
1252 | this->list(pfn, varg, true); | |
1253 | if (!this->peek_token()->is_op(OPERATOR_RPAREN)) | |
1254 | { | |
1255 | error_at(this->location(), "missing %<)%>"); | |
1256 | while (!this->advance_token()->is_op(OPERATOR_RPAREN)) | |
1257 | { | |
1258 | if (this->peek_token()->is_eof()) | |
1259 | return; | |
1260 | } | |
1261 | } | |
1262 | } | |
1263 | this->advance_token(); | |
1264 | } | |
1265 | } | |
1266 | ||
1267 | // List<P> = P { ";" P } [ ";" ] . | |
1268 | ||
1269 | // In order to pick up the trailing semicolon we need to know what | |
1270 | // might follow. This is either a '}' or a ')'. | |
1271 | ||
1272 | void | |
1273 | Parse::list(void (Parse::*pfn)(void*), void* varg, bool follow_is_paren) | |
1274 | { | |
1275 | (this->*pfn)(varg); | |
1276 | Operator follow = follow_is_paren ? OPERATOR_RPAREN : OPERATOR_RCURLY; | |
1277 | while (this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
1278 | || this->peek_token()->is_op(OPERATOR_COMMA)) | |
1279 | { | |
1280 | if (this->peek_token()->is_op(OPERATOR_COMMA)) | |
1281 | error_at(this->location(), "unexpected comma"); | |
1282 | if (this->advance_token()->is_op(follow)) | |
1283 | break; | |
1284 | (this->*pfn)(varg); | |
1285 | } | |
1286 | } | |
1287 | ||
1288 | // ConstDecl = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) . | |
1289 | ||
1290 | void | |
1291 | Parse::const_decl() | |
1292 | { | |
1293 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_CONST)); | |
1294 | this->advance_token(); | |
1295 | this->reset_iota(); | |
1296 | ||
1297 | Type* last_type = NULL; | |
1298 | Expression_list* last_expr_list = NULL; | |
1299 | ||
1300 | if (!this->peek_token()->is_op(OPERATOR_LPAREN)) | |
1301 | this->const_spec(&last_type, &last_expr_list); | |
1302 | else | |
1303 | { | |
1304 | this->advance_token(); | |
1305 | while (!this->peek_token()->is_op(OPERATOR_RPAREN)) | |
1306 | { | |
1307 | this->const_spec(&last_type, &last_expr_list); | |
1308 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
1309 | this->advance_token(); | |
1310 | else if (!this->peek_token()->is_op(OPERATOR_RPAREN)) | |
1311 | { | |
1312 | error_at(this->location(), "expected %<;%> or %<)%> or newline"); | |
1313 | if (!this->skip_past_error(OPERATOR_RPAREN)) | |
1314 | return; | |
1315 | } | |
1316 | } | |
1317 | this->advance_token(); | |
1318 | } | |
1319 | ||
1320 | if (last_expr_list != NULL) | |
1321 | delete last_expr_list; | |
1322 | } | |
1323 | ||
1324 | // ConstSpec = IdentifierList [ [ CompleteType ] "=" ExpressionList ] . | |
1325 | ||
1326 | void | |
1327 | Parse::const_spec(Type** last_type, Expression_list** last_expr_list) | |
1328 | { | |
1329 | Typed_identifier_list til; | |
1330 | this->identifier_list(&til); | |
1331 | ||
1332 | Type* type = NULL; | |
1333 | if (this->type_may_start_here()) | |
1334 | { | |
1335 | type = this->type(); | |
1336 | *last_type = NULL; | |
1337 | *last_expr_list = NULL; | |
1338 | } | |
1339 | ||
1340 | Expression_list *expr_list; | |
1341 | if (!this->peek_token()->is_op(OPERATOR_EQ)) | |
1342 | { | |
1343 | if (*last_expr_list == NULL) | |
1344 | { | |
1345 | error_at(this->location(), "expected %<=%>"); | |
1346 | return; | |
1347 | } | |
1348 | type = *last_type; | |
1349 | expr_list = new Expression_list; | |
1350 | for (Expression_list::const_iterator p = (*last_expr_list)->begin(); | |
1351 | p != (*last_expr_list)->end(); | |
1352 | ++p) | |
1353 | expr_list->push_back((*p)->copy()); | |
1354 | } | |
1355 | else | |
1356 | { | |
1357 | this->advance_token(); | |
1358 | expr_list = this->expression_list(NULL, false); | |
1359 | *last_type = type; | |
1360 | if (*last_expr_list != NULL) | |
1361 | delete *last_expr_list; | |
1362 | *last_expr_list = expr_list; | |
1363 | } | |
1364 | ||
1365 | Expression_list::const_iterator pe = expr_list->begin(); | |
1366 | for (Typed_identifier_list::iterator pi = til.begin(); | |
1367 | pi != til.end(); | |
1368 | ++pi, ++pe) | |
1369 | { | |
1370 | if (pe == expr_list->end()) | |
1371 | { | |
1372 | error_at(this->location(), "not enough initializers"); | |
1373 | return; | |
1374 | } | |
1375 | if (type != NULL) | |
1376 | pi->set_type(type); | |
1377 | ||
1378 | if (!Gogo::is_sink_name(pi->name())) | |
1379 | this->gogo_->add_constant(*pi, *pe, this->iota_value()); | |
1380 | } | |
1381 | if (pe != expr_list->end()) | |
1382 | error_at(this->location(), "too many initializers"); | |
1383 | ||
1384 | this->increment_iota(); | |
1385 | ||
1386 | return; | |
1387 | } | |
1388 | ||
1389 | // TypeDecl = "type" Decl<TypeSpec> . | |
1390 | ||
1391 | void | |
1392 | Parse::type_decl() | |
1393 | { | |
1394 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_TYPE)); | |
1395 | this->advance_token(); | |
1396 | this->decl(&Parse::type_spec, NULL); | |
1397 | } | |
1398 | ||
1399 | // TypeSpec = identifier Type . | |
1400 | ||
1401 | void | |
1402 | Parse::type_spec(void*) | |
1403 | { | |
1404 | const Token* token = this->peek_token(); | |
1405 | if (!token->is_identifier()) | |
1406 | { | |
1407 | error_at(this->location(), "expected identifier"); | |
1408 | return; | |
1409 | } | |
1410 | std::string name = token->identifier(); | |
1411 | bool is_exported = token->is_identifier_exported(); | |
1412 | source_location location = token->location(); | |
1413 | token = this->advance_token(); | |
1414 | ||
1415 | // The scope of the type name starts at the point where the | |
1416 | // identifier appears in the source code. We implement this by | |
1417 | // declaring the type before we read the type definition. | |
1418 | Named_object* named_type = NULL; | |
1419 | if (name != "_") | |
1420 | { | |
1421 | name = this->gogo_->pack_hidden_name(name, is_exported); | |
1422 | named_type = this->gogo_->declare_type(name, location); | |
1423 | } | |
1424 | ||
1425 | Type* type; | |
1426 | if (!this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
1427 | type = this->type(); | |
1428 | else | |
1429 | { | |
1430 | error_at(this->location(), | |
1431 | "unexpected semicolon or newline in type declaration"); | |
1432 | type = Type::make_error_type(); | |
1433 | this->advance_token(); | |
1434 | } | |
1435 | ||
1436 | if (type->is_error_type()) | |
1437 | { | |
1438 | while (!this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
1439 | && !this->peek_token()->is_eof()) | |
1440 | this->advance_token(); | |
1441 | } | |
1442 | ||
1443 | if (name != "_") | |
1444 | { | |
1445 | if (named_type->is_type_declaration()) | |
1446 | { | |
1447 | Type* ftype = type->forwarded(); | |
1448 | if (ftype->forward_declaration_type() != NULL | |
1449 | && (ftype->forward_declaration_type()->named_object() | |
1450 | == named_type)) | |
1451 | { | |
1452 | error_at(location, "invalid recursive type"); | |
1453 | type = Type::make_error_type(); | |
1454 | } | |
1455 | ||
1456 | this->gogo_->define_type(named_type, | |
1457 | Type::make_named_type(named_type, type, | |
1458 | location)); | |
1459 | gcc_assert(named_type->package() == NULL); | |
1460 | } | |
1461 | else | |
1462 | { | |
1463 | // This will probably give a redefinition error. | |
1464 | this->gogo_->add_type(name, type, location); | |
1465 | } | |
1466 | } | |
1467 | } | |
1468 | ||
1469 | // VarDecl = "var" Decl<VarSpec> . | |
1470 | ||
1471 | void | |
1472 | Parse::var_decl() | |
1473 | { | |
1474 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_VAR)); | |
1475 | this->advance_token(); | |
1476 | this->decl(&Parse::var_spec, NULL); | |
1477 | } | |
1478 | ||
1479 | // VarSpec = IdentifierList | |
1480 | // ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) . | |
1481 | ||
1482 | void | |
1483 | Parse::var_spec(void*) | |
1484 | { | |
1485 | // Get the variable names. | |
1486 | Typed_identifier_list til; | |
1487 | this->identifier_list(&til); | |
1488 | ||
1489 | source_location location = this->location(); | |
1490 | ||
1491 | Type* type = NULL; | |
1492 | Expression_list* init = NULL; | |
1493 | if (!this->peek_token()->is_op(OPERATOR_EQ)) | |
1494 | { | |
1495 | type = this->type(); | |
1496 | if (type->is_error_type()) | |
1497 | { | |
1498 | while (!this->peek_token()->is_op(OPERATOR_EQ) | |
1499 | && !this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
1500 | && !this->peek_token()->is_eof()) | |
1501 | this->advance_token(); | |
1502 | } | |
1503 | if (this->peek_token()->is_op(OPERATOR_EQ)) | |
1504 | { | |
1505 | this->advance_token(); | |
1506 | init = this->expression_list(NULL, false); | |
1507 | } | |
1508 | } | |
1509 | else | |
1510 | { | |
1511 | this->advance_token(); | |
1512 | init = this->expression_list(NULL, false); | |
1513 | } | |
1514 | ||
1515 | this->init_vars(&til, type, init, false, location); | |
1516 | ||
1517 | if (init != NULL) | |
1518 | delete init; | |
1519 | } | |
1520 | ||
1521 | // Create variables. TIL is a list of variable names. If TYPE is not | |
1522 | // NULL, it is the type of all the variables. If INIT is not NULL, it | |
1523 | // is an initializer list for the variables. | |
1524 | ||
1525 | void | |
1526 | Parse::init_vars(const Typed_identifier_list* til, Type* type, | |
1527 | Expression_list* init, bool is_coloneq, | |
1528 | source_location location) | |
1529 | { | |
1530 | // Check for an initialization which can yield multiple values. | |
1531 | if (init != NULL && init->size() == 1 && til->size() > 1) | |
1532 | { | |
1533 | if (this->init_vars_from_call(til, type, *init->begin(), is_coloneq, | |
1534 | location)) | |
1535 | return; | |
1536 | if (this->init_vars_from_map(til, type, *init->begin(), is_coloneq, | |
1537 | location)) | |
1538 | return; | |
1539 | if (this->init_vars_from_receive(til, type, *init->begin(), is_coloneq, | |
1540 | location)) | |
1541 | return; | |
1542 | if (this->init_vars_from_type_guard(til, type, *init->begin(), | |
1543 | is_coloneq, location)) | |
1544 | return; | |
1545 | } | |
1546 | ||
1547 | if (init != NULL && init->size() != til->size()) | |
1548 | { | |
1549 | if (init->empty() || !init->front()->is_error_expression()) | |
1550 | error_at(location, "wrong number of initializations"); | |
1551 | init = NULL; | |
1552 | if (type == NULL) | |
1553 | type = Type::make_error_type(); | |
1554 | } | |
1555 | ||
1556 | // Note that INIT was already parsed with the old name bindings, so | |
1557 | // we don't have to worry that it will accidentally refer to the | |
1558 | // newly declared variables. | |
1559 | ||
1560 | Expression_list::const_iterator pexpr; | |
1561 | if (init != NULL) | |
1562 | pexpr = init->begin(); | |
1563 | bool any_new = false; | |
1564 | for (Typed_identifier_list::const_iterator p = til->begin(); | |
1565 | p != til->end(); | |
1566 | ++p) | |
1567 | { | |
1568 | if (init != NULL) | |
1569 | gcc_assert(pexpr != init->end()); | |
1570 | this->init_var(*p, type, init == NULL ? NULL : *pexpr, is_coloneq, | |
1571 | false, &any_new); | |
1572 | if (init != NULL) | |
1573 | ++pexpr; | |
1574 | } | |
1575 | if (init != NULL) | |
1576 | gcc_assert(pexpr == init->end()); | |
1577 | if (is_coloneq && !any_new) | |
1578 | error_at(location, "variables redeclared but no variable is new"); | |
1579 | } | |
1580 | ||
1581 | // See if we need to initialize a list of variables from a function | |
1582 | // call. This returns true if we have set up the variables and the | |
1583 | // initialization. | |
1584 | ||
1585 | bool | |
1586 | Parse::init_vars_from_call(const Typed_identifier_list* vars, Type* type, | |
1587 | Expression* expr, bool is_coloneq, | |
1588 | source_location location) | |
1589 | { | |
1590 | Call_expression* call = expr->call_expression(); | |
1591 | if (call == NULL) | |
1592 | return false; | |
1593 | ||
1594 | // This is a function call. We can't check here whether it returns | |
1595 | // the right number of values, but it might. Declare the variables, | |
1596 | // and then assign the results of the call to them. | |
1597 | ||
1598 | unsigned int index = 0; | |
1599 | bool any_new = false; | |
1600 | for (Typed_identifier_list::const_iterator pv = vars->begin(); | |
1601 | pv != vars->end(); | |
1602 | ++pv, ++index) | |
1603 | { | |
1604 | Expression* init = Expression::make_call_result(call, index); | |
1605 | this->init_var(*pv, type, init, is_coloneq, false, &any_new); | |
1606 | } | |
1607 | ||
1608 | if (is_coloneq && !any_new) | |
1609 | error_at(location, "variables redeclared but no variable is new"); | |
1610 | ||
1611 | return true; | |
1612 | } | |
1613 | ||
1614 | // See if we need to initialize a pair of values from a map index | |
1615 | // expression. This returns true if we have set up the variables and | |
1616 | // the initialization. | |
1617 | ||
1618 | bool | |
1619 | Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type, | |
1620 | Expression* expr, bool is_coloneq, | |
1621 | source_location location) | |
1622 | { | |
1623 | Index_expression* index = expr->index_expression(); | |
1624 | if (index == NULL) | |
1625 | return false; | |
1626 | if (vars->size() != 2) | |
1627 | return false; | |
1628 | ||
1629 | // This is an index which is being assigned to two variables. It | |
1630 | // must be a map index. Declare the variables, and then assign the | |
1631 | // results of the map index. | |
1632 | bool any_new = false; | |
1633 | Typed_identifier_list::const_iterator p = vars->begin(); | |
1634 | Expression* init = type == NULL ? index : NULL; | |
1635 | Named_object* val_no = this->init_var(*p, type, init, is_coloneq, | |
1636 | type == NULL, &any_new); | |
1637 | if (type == NULL && any_new && val_no->is_variable()) | |
1638 | val_no->var_value()->set_type_from_init_tuple(); | |
1639 | Expression* val_var = Expression::make_var_reference(val_no, location); | |
1640 | ||
1641 | ++p; | |
1642 | Type* var_type = type; | |
1643 | if (var_type == NULL) | |
1644 | var_type = Type::lookup_bool_type(); | |
1645 | Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false, | |
1646 | &any_new); | |
1647 | Expression* present_var = Expression::make_var_reference(no, location); | |
1648 | ||
1649 | if (is_coloneq && !any_new) | |
1650 | error_at(location, "variables redeclared but no variable is new"); | |
1651 | ||
1652 | Statement* s = Statement::make_tuple_map_assignment(val_var, present_var, | |
1653 | index, location); | |
1654 | ||
1655 | if (!this->gogo_->in_global_scope()) | |
1656 | this->gogo_->add_statement(s); | |
8332d80e | 1657 | else if (!val_no->is_sink()) |
eb83e2d7 ILT |
1658 | { |
1659 | if (val_no->is_variable()) | |
1660 | val_no->var_value()->add_preinit_statement(s); | |
1661 | } | |
8332d80e | 1662 | else if (!no->is_sink()) |
eb83e2d7 ILT |
1663 | { |
1664 | if (no->is_variable()) | |
1665 | no->var_value()->add_preinit_statement(s); | |
1666 | } | |
8332d80e ILT |
1667 | else |
1668 | { | |
1669 | // Execute the map index expression just so that we can fail if | |
1670 | // the map is nil. | |
1671 | Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(), | |
1672 | NULL, location); | |
1673 | dummy->var_value()->add_preinit_statement(s); | |
1674 | } | |
7a938933 ILT |
1675 | |
1676 | return true; | |
1677 | } | |
1678 | ||
1679 | // See if we need to initialize a pair of values from a receive | |
1680 | // expression. This returns true if we have set up the variables and | |
1681 | // the initialization. | |
1682 | ||
1683 | bool | |
1684 | Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type, | |
1685 | Expression* expr, bool is_coloneq, | |
1686 | source_location location) | |
1687 | { | |
1688 | Receive_expression* receive = expr->receive_expression(); | |
1689 | if (receive == NULL) | |
1690 | return false; | |
1691 | if (vars->size() != 2) | |
1692 | return false; | |
1693 | ||
1694 | // This is a receive expression which is being assigned to two | |
1695 | // variables. Declare the variables, and then assign the results of | |
1696 | // the receive. | |
1697 | bool any_new = false; | |
1698 | Typed_identifier_list::const_iterator p = vars->begin(); | |
1699 | Expression* init = type == NULL ? receive : NULL; | |
1700 | Named_object* val_no = this->init_var(*p, type, init, is_coloneq, | |
1701 | type == NULL, &any_new); | |
1702 | if (type == NULL && any_new && val_no->is_variable()) | |
1703 | val_no->var_value()->set_type_from_init_tuple(); | |
1704 | Expression* val_var = Expression::make_var_reference(val_no, location); | |
1705 | ||
1706 | ++p; | |
1707 | Type* var_type = type; | |
1708 | if (var_type == NULL) | |
1709 | var_type = Type::lookup_bool_type(); | |
1710 | Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false, | |
1711 | &any_new); | |
1712 | Expression* received_var = Expression::make_var_reference(no, location); | |
1713 | ||
1714 | if (is_coloneq && !any_new) | |
1715 | error_at(location, "variables redeclared but no variable is new"); | |
1716 | ||
1717 | Statement* s = Statement::make_tuple_receive_assignment(val_var, | |
1718 | received_var, | |
1719 | receive->channel(), | |
1720 | location); | |
1721 | ||
1722 | if (!this->gogo_->in_global_scope()) | |
1723 | this->gogo_->add_statement(s); | |
8332d80e | 1724 | else if (!val_no->is_sink()) |
eb83e2d7 ILT |
1725 | { |
1726 | if (val_no->is_variable()) | |
1727 | val_no->var_value()->add_preinit_statement(s); | |
1728 | } | |
8332d80e | 1729 | else if (!no->is_sink()) |
eb83e2d7 ILT |
1730 | { |
1731 | if (no->is_variable()) | |
1732 | no->var_value()->add_preinit_statement(s); | |
1733 | } | |
8332d80e ILT |
1734 | else |
1735 | { | |
1736 | Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(), | |
1737 | NULL, location); | |
1738 | dummy->var_value()->add_preinit_statement(s); | |
1739 | } | |
7a938933 ILT |
1740 | |
1741 | return true; | |
1742 | } | |
1743 | ||
1744 | // See if we need to initialize a pair of values from a type guard | |
1745 | // expression. This returns true if we have set up the variables and | |
1746 | // the initialization. | |
1747 | ||
1748 | bool | |
1749 | Parse::init_vars_from_type_guard(const Typed_identifier_list* vars, | |
1750 | Type* type, Expression* expr, | |
1751 | bool is_coloneq, source_location location) | |
1752 | { | |
1753 | Type_guard_expression* type_guard = expr->type_guard_expression(); | |
1754 | if (type_guard == NULL) | |
1755 | return false; | |
1756 | if (vars->size() != 2) | |
1757 | return false; | |
1758 | ||
1759 | // This is a type guard expression which is being assigned to two | |
1760 | // variables. Declare the variables, and then assign the results of | |
1761 | // the type guard. | |
1762 | bool any_new = false; | |
1763 | Typed_identifier_list::const_iterator p = vars->begin(); | |
1764 | Type* var_type = type; | |
1765 | if (var_type == NULL) | |
1766 | var_type = type_guard->type(); | |
1767 | Named_object* val_no = this->init_var(*p, var_type, NULL, is_coloneq, false, | |
1768 | &any_new); | |
1769 | Expression* val_var = Expression::make_var_reference(val_no, location); | |
1770 | ||
1771 | ++p; | |
1772 | var_type = type; | |
1773 | if (var_type == NULL) | |
1774 | var_type = Type::lookup_bool_type(); | |
1775 | Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false, | |
1776 | &any_new); | |
1777 | Expression* ok_var = Expression::make_var_reference(no, location); | |
1778 | ||
1779 | Expression* texpr = type_guard->expr(); | |
1780 | Type* t = type_guard->type(); | |
1781 | Statement* s = Statement::make_tuple_type_guard_assignment(val_var, ok_var, | |
1782 | texpr, t, | |
1783 | location); | |
1784 | ||
1785 | if (is_coloneq && !any_new) | |
1786 | error_at(location, "variables redeclared but no variable is new"); | |
1787 | ||
1788 | if (!this->gogo_->in_global_scope()) | |
1789 | this->gogo_->add_statement(s); | |
8332d80e | 1790 | else if (!val_no->is_sink()) |
eb83e2d7 ILT |
1791 | { |
1792 | if (val_no->is_variable()) | |
1793 | val_no->var_value()->add_preinit_statement(s); | |
1794 | } | |
8332d80e | 1795 | else if (!no->is_sink()) |
eb83e2d7 ILT |
1796 | { |
1797 | if (no->is_variable()) | |
1798 | no->var_value()->add_preinit_statement(s); | |
1799 | } | |
8332d80e ILT |
1800 | else |
1801 | { | |
1802 | Named_object* dummy = this->create_dummy_global(type, NULL, location); | |
1803 | dummy->var_value()->add_preinit_statement(s); | |
1804 | } | |
7a938933 ILT |
1805 | |
1806 | return true; | |
1807 | } | |
1808 | ||
1809 | // Create a single variable. If IS_COLONEQ is true, we permit | |
1810 | // redeclarations in the same block, and we set *IS_NEW when we find a | |
1811 | // new variable which is not a redeclaration. | |
1812 | ||
1813 | Named_object* | |
1814 | Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init, | |
1815 | bool is_coloneq, bool type_from_init, bool* is_new) | |
1816 | { | |
1817 | source_location location = tid.location(); | |
1818 | ||
1819 | if (Gogo::is_sink_name(tid.name())) | |
1820 | { | |
1821 | if (!type_from_init && init != NULL) | |
1822 | { | |
1823 | if (!this->gogo_->in_global_scope()) | |
1824 | this->gogo_->add_statement(Statement::make_statement(init)); | |
1825 | else | |
8332d80e | 1826 | return this->create_dummy_global(type, init, location); |
7a938933 ILT |
1827 | } |
1828 | return this->gogo_->add_sink(); | |
1829 | } | |
1830 | ||
1831 | if (is_coloneq) | |
1832 | { | |
1833 | Named_object* no = this->gogo_->lookup_in_block(tid.name()); | |
1834 | if (no != NULL | |
1835 | && (no->is_variable() || no->is_result_variable())) | |
1836 | { | |
1837 | // INIT may be NULL even when IS_COLONEQ is true for cases | |
1838 | // like v, ok := x.(int). | |
1839 | if (!type_from_init && init != NULL) | |
1840 | { | |
1841 | Expression *v = Expression::make_var_reference(no, location); | |
1842 | Statement *s = Statement::make_assignment(v, init, location); | |
1843 | this->gogo_->add_statement(s); | |
1844 | } | |
1845 | return no; | |
1846 | } | |
1847 | } | |
1848 | *is_new = true; | |
1849 | Variable* var = new Variable(type, init, this->gogo_->in_global_scope(), | |
1850 | false, false, location); | |
1851 | return this->gogo_->add_variable(tid.name(), var); | |
1852 | } | |
1853 | ||
8332d80e ILT |
1854 | // Create a dummy global variable to force an initializer to be run in |
1855 | // the right place. This is used when a sink variable is initialized | |
1856 | // at global scope. | |
1857 | ||
1858 | Named_object* | |
1859 | Parse::create_dummy_global(Type* type, Expression* init, | |
1860 | source_location location) | |
1861 | { | |
1862 | Variable* var = new Variable(type, init, true, false, false, location); | |
1863 | static int count; | |
1864 | char buf[30]; | |
1865 | snprintf(buf, sizeof buf, "_.%d", count); | |
1866 | ++count; | |
1867 | return this->gogo_->add_variable(buf, var); | |
1868 | } | |
1869 | ||
7a938933 ILT |
1870 | // SimpleVarDecl = identifier ":=" Expression . |
1871 | ||
1872 | // We've already seen the identifier. | |
1873 | ||
1874 | // FIXME: We also have to implement | |
1875 | // IdentifierList ":=" ExpressionList | |
1876 | // In order to support both "a, b := 1, 0" and "a, b = 1, 0" we accept | |
1877 | // tuple assignments here as well. | |
1878 | ||
1879 | // If P_RANGE_CLAUSE is not NULL, then this will recognize a | |
1880 | // RangeClause. | |
1881 | ||
1882 | // If P_TYPE_SWITCH is not NULL, this will recognize a type switch | |
1883 | // guard (var := expr.("type") using the literal keyword "type"). | |
1884 | ||
1885 | void | |
1886 | Parse::simple_var_decl_or_assignment(const std::string& name, | |
1887 | source_location location, | |
1888 | Range_clause* p_range_clause, | |
1889 | Type_switch* p_type_switch) | |
1890 | { | |
1891 | Typed_identifier_list til; | |
1892 | til.push_back(Typed_identifier(name, NULL, location)); | |
1893 | ||
1894 | // We've seen one identifier. If we see a comma now, this could be | |
1895 | // "a, *p = 1, 2". | |
1896 | if (this->peek_token()->is_op(OPERATOR_COMMA)) | |
1897 | { | |
1898 | gcc_assert(p_type_switch == NULL); | |
1899 | while (true) | |
1900 | { | |
1901 | const Token* token = this->advance_token(); | |
1902 | if (!token->is_identifier()) | |
1903 | break; | |
1904 | ||
1905 | std::string id = token->identifier(); | |
1906 | bool is_id_exported = token->is_identifier_exported(); | |
1907 | source_location id_location = token->location(); | |
1908 | ||
1909 | token = this->advance_token(); | |
1910 | if (!token->is_op(OPERATOR_COMMA)) | |
1911 | { | |
1912 | if (token->is_op(OPERATOR_COLONEQ)) | |
1913 | { | |
1914 | id = this->gogo_->pack_hidden_name(id, is_id_exported); | |
1915 | til.push_back(Typed_identifier(id, NULL, location)); | |
1916 | } | |
1917 | else | |
1918 | this->unget_token(Token::make_identifier_token(id, | |
1919 | is_id_exported, | |
1920 | id_location)); | |
1921 | break; | |
1922 | } | |
1923 | ||
1924 | id = this->gogo_->pack_hidden_name(id, is_id_exported); | |
1925 | til.push_back(Typed_identifier(id, NULL, location)); | |
1926 | } | |
1927 | ||
1928 | // We have a comma separated list of identifiers in TIL. If the | |
1929 | // next token is COLONEQ, then this is a simple var decl, and we | |
1930 | // have the complete list of identifiers. If the next token is | |
1931 | // not COLONEQ, then the only valid parse is a tuple assignment. | |
1932 | // The list of identifiers we have so far is really a list of | |
1933 | // expressions. There are more expressions following. | |
1934 | ||
1935 | if (!this->peek_token()->is_op(OPERATOR_COLONEQ)) | |
1936 | { | |
1937 | Expression_list* exprs = new Expression_list; | |
1938 | for (Typed_identifier_list::const_iterator p = til.begin(); | |
1939 | p != til.end(); | |
1940 | ++p) | |
1941 | exprs->push_back(this->id_to_expression(p->name(), | |
1942 | p->location())); | |
1943 | ||
1944 | Expression_list* more_exprs = this->expression_list(NULL, true); | |
1945 | for (Expression_list::const_iterator p = more_exprs->begin(); | |
1946 | p != more_exprs->end(); | |
1947 | ++p) | |
1948 | exprs->push_back(*p); | |
1949 | delete more_exprs; | |
1950 | ||
1951 | this->tuple_assignment(exprs, p_range_clause); | |
1952 | return; | |
1953 | } | |
1954 | } | |
1955 | ||
1956 | gcc_assert(this->peek_token()->is_op(OPERATOR_COLONEQ)); | |
1957 | const Token* token = this->advance_token(); | |
1958 | ||
1959 | if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE)) | |
1960 | { | |
1961 | this->range_clause_decl(&til, p_range_clause); | |
1962 | return; | |
1963 | } | |
1964 | ||
1965 | Expression_list* init; | |
1966 | if (p_type_switch == NULL) | |
1967 | init = this->expression_list(NULL, false); | |
1968 | else | |
1969 | { | |
1970 | bool is_type_switch = false; | |
1971 | Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, | |
1972 | &is_type_switch); | |
1973 | if (is_type_switch) | |
1974 | { | |
1975 | p_type_switch->found = true; | |
1976 | p_type_switch->name = name; | |
1977 | p_type_switch->location = location; | |
1978 | p_type_switch->expr = expr; | |
1979 | return; | |
1980 | } | |
1981 | ||
1982 | if (!this->peek_token()->is_op(OPERATOR_COMMA)) | |
1983 | { | |
1984 | init = new Expression_list(); | |
1985 | init->push_back(expr); | |
1986 | } | |
1987 | else | |
1988 | { | |
1989 | this->advance_token(); | |
1990 | init = this->expression_list(expr, false); | |
1991 | } | |
1992 | } | |
1993 | ||
1994 | this->init_vars(&til, NULL, init, true, location); | |
1995 | } | |
1996 | ||
1997 | // FunctionDecl = "func" identifier Signature [ Block ] . | |
1998 | // MethodDecl = "func" Receiver identifier Signature [ Block ] . | |
1999 | ||
2000 | // gcc extension: | |
2001 | // FunctionDecl = "func" identifier Signature | |
2002 | // __asm__ "(" string_lit ")" . | |
2003 | // This extension means a function whose real name is the identifier | |
2004 | // inside the asm. | |
2005 | ||
2006 | void | |
2007 | Parse::function_decl() | |
2008 | { | |
2009 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_FUNC)); | |
2010 | source_location location = this->location(); | |
2011 | const Token* token = this->advance_token(); | |
2012 | ||
2013 | Typed_identifier* rec = NULL; | |
2014 | if (token->is_op(OPERATOR_LPAREN)) | |
2015 | { | |
2016 | rec = this->receiver(); | |
2017 | token = this->peek_token(); | |
2018 | } | |
2019 | ||
2020 | if (!token->is_identifier()) | |
2021 | { | |
2022 | error_at(this->location(), "expected function name"); | |
2023 | return; | |
2024 | } | |
2025 | ||
2026 | std::string name = | |
2027 | this->gogo_->pack_hidden_name(token->identifier(), | |
2028 | token->is_identifier_exported()); | |
2029 | ||
2030 | this->advance_token(); | |
2031 | ||
2032 | Function_type* fntype = this->signature(rec, this->location()); | |
cad51bed ILT |
2033 | if (fntype == NULL) |
2034 | return; | |
7a938933 ILT |
2035 | |
2036 | Named_object* named_object = NULL; | |
2037 | ||
2038 | if (this->peek_token()->is_keyword(KEYWORD_ASM)) | |
2039 | { | |
2040 | if (!this->advance_token()->is_op(OPERATOR_LPAREN)) | |
2041 | { | |
2042 | error_at(this->location(), "expected %<(%>"); | |
2043 | return; | |
2044 | } | |
2045 | token = this->advance_token(); | |
2046 | if (!token->is_string()) | |
2047 | { | |
2048 | error_at(this->location(), "expected string"); | |
2049 | return; | |
2050 | } | |
2051 | std::string asm_name = token->string_value(); | |
2052 | if (!this->advance_token()->is_op(OPERATOR_RPAREN)) | |
2053 | { | |
2054 | error_at(this->location(), "expected %<)%>"); | |
2055 | return; | |
2056 | } | |
2057 | this->advance_token(); | |
2058 | named_object = this->gogo_->declare_function(name, fntype, location); | |
2059 | if (named_object->is_function_declaration()) | |
2060 | named_object->func_declaration_value()->set_asm_name(asm_name); | |
2061 | } | |
2062 | ||
2063 | // Check for the easy error of a newline before the opening brace. | |
2064 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
2065 | { | |
2066 | source_location semi_loc = this->location(); | |
2067 | if (this->advance_token()->is_op(OPERATOR_LCURLY)) | |
2068 | error_at(this->location(), | |
2069 | "unexpected semicolon or newline before %<{%>"); | |
2070 | else | |
2071 | this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON, | |
2072 | semi_loc)); | |
2073 | } | |
2074 | ||
2075 | if (!this->peek_token()->is_op(OPERATOR_LCURLY)) | |
2076 | { | |
2077 | if (named_object == NULL) | |
2078 | named_object = this->gogo_->declare_function(name, fntype, location); | |
2079 | } | |
2080 | else | |
2081 | { | |
2082 | this->gogo_->start_function(name, fntype, true, location); | |
2083 | source_location end_loc = this->block(); | |
2084 | this->gogo_->finish_function(end_loc); | |
2085 | } | |
2086 | } | |
2087 | ||
2088 | // Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . | |
2089 | // BaseTypeName = identifier . | |
2090 | ||
2091 | Typed_identifier* | |
2092 | Parse::receiver() | |
2093 | { | |
2094 | gcc_assert(this->peek_token()->is_op(OPERATOR_LPAREN)); | |
2095 | ||
2096 | std::string name; | |
2097 | const Token* token = this->advance_token(); | |
2098 | source_location location = token->location(); | |
2099 | if (!token->is_op(OPERATOR_MULT)) | |
2100 | { | |
2101 | if (!token->is_identifier()) | |
2102 | { | |
2103 | error_at(this->location(), "method has no receiver"); | |
2104 | while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN)) | |
2105 | token = this->advance_token(); | |
2106 | if (!token->is_eof()) | |
2107 | this->advance_token(); | |
2108 | return NULL; | |
2109 | } | |
2110 | name = token->identifier(); | |
2111 | bool is_exported = token->is_identifier_exported(); | |
2112 | token = this->advance_token(); | |
2113 | if (!token->is_op(OPERATOR_DOT) && !token->is_op(OPERATOR_RPAREN)) | |
2114 | { | |
2115 | // An identifier followed by something other than a dot or a | |
2116 | // right parenthesis must be a receiver name followed by a | |
2117 | // type. | |
2118 | name = this->gogo_->pack_hidden_name(name, is_exported); | |
2119 | } | |
2120 | else | |
2121 | { | |
2122 | // This must be a type name. | |
2123 | this->unget_token(Token::make_identifier_token(name, is_exported, | |
2124 | location)); | |
2125 | token = this->peek_token(); | |
2126 | name.clear(); | |
2127 | } | |
2128 | } | |
2129 | ||
2130 | // Here the receiver name is in NAME (it is empty if the receiver is | |
2131 | // unnamed) and TOKEN is the first token in the type. | |
2132 | ||
2133 | bool is_pointer = false; | |
2134 | if (token->is_op(OPERATOR_MULT)) | |
2135 | { | |
2136 | is_pointer = true; | |
2137 | token = this->advance_token(); | |
2138 | } | |
2139 | ||
2140 | if (!token->is_identifier()) | |
2141 | { | |
2142 | error_at(this->location(), "expected receiver name or type"); | |
2143 | int c = token->is_op(OPERATOR_LPAREN) ? 1 : 0; | |
2144 | while (!token->is_eof()) | |
2145 | { | |
2146 | token = this->advance_token(); | |
2147 | if (token->is_op(OPERATOR_LPAREN)) | |
2148 | ++c; | |
2149 | else if (token->is_op(OPERATOR_RPAREN)) | |
2150 | { | |
2151 | if (c == 0) | |
2152 | break; | |
2153 | --c; | |
2154 | } | |
2155 | } | |
2156 | if (!token->is_eof()) | |
2157 | this->advance_token(); | |
2158 | return NULL; | |
2159 | } | |
2160 | ||
2161 | Type* type = this->type_name(true); | |
2162 | ||
2163 | if (is_pointer && !type->is_error_type()) | |
2164 | type = Type::make_pointer_type(type); | |
2165 | ||
2166 | if (this->peek_token()->is_op(OPERATOR_RPAREN)) | |
2167 | this->advance_token(); | |
2168 | else | |
2169 | { | |
2170 | if (this->peek_token()->is_op(OPERATOR_COMMA)) | |
2171 | error_at(this->location(), "method has multiple receivers"); | |
2172 | else | |
2173 | error_at(this->location(), "expected %<)%>"); | |
2174 | while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN)) | |
2175 | token = this->advance_token(); | |
2176 | if (!token->is_eof()) | |
2177 | this->advance_token(); | |
2178 | return NULL; | |
2179 | } | |
2180 | ||
2181 | return new Typed_identifier(name, type, location); | |
2182 | } | |
2183 | ||
2184 | // Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" . | |
2185 | // Literal = BasicLit | CompositeLit | FunctionLit . | |
2186 | // BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit . | |
2187 | ||
2188 | // If MAY_BE_SINK is true, this operand may be "_". | |
2189 | ||
2190 | Expression* | |
2191 | Parse::operand(bool may_be_sink) | |
2192 | { | |
2193 | const Token* token = this->peek_token(); | |
2194 | Expression* ret; | |
2195 | switch (token->classification()) | |
2196 | { | |
2197 | case Token::TOKEN_IDENTIFIER: | |
2198 | { | |
2199 | source_location location = token->location(); | |
2200 | std::string id = token->identifier(); | |
2201 | bool is_exported = token->is_identifier_exported(); | |
2202 | std::string packed = this->gogo_->pack_hidden_name(id, is_exported); | |
2203 | ||
2204 | Named_object* in_function; | |
2205 | Named_object* named_object = this->gogo_->lookup(packed, &in_function); | |
2206 | ||
2207 | Package* package = NULL; | |
2208 | if (named_object != NULL && named_object->is_package()) | |
2209 | { | |
2210 | if (!this->advance_token()->is_op(OPERATOR_DOT) | |
2211 | || !this->advance_token()->is_identifier()) | |
2212 | { | |
2213 | error_at(location, "unexpected reference to package"); | |
2214 | return Expression::make_error(location); | |
2215 | } | |
2216 | package = named_object->package_value(); | |
2217 | package->set_used(); | |
2218 | id = this->peek_token()->identifier(); | |
2219 | is_exported = this->peek_token()->is_identifier_exported(); | |
2220 | packed = this->gogo_->pack_hidden_name(id, is_exported); | |
2221 | named_object = package->lookup(packed); | |
2222 | location = this->location(); | |
2223 | gcc_assert(in_function == NULL); | |
2224 | } | |
2225 | ||
2226 | this->advance_token(); | |
2227 | ||
2228 | if (named_object != NULL | |
2229 | && named_object->is_type() | |
2230 | && !named_object->type_value()->is_visible()) | |
2231 | { | |
2232 | gcc_assert(package != NULL); | |
2233 | error_at(location, "invalid reference to hidden type %<%s.%s%>", | |
2234 | Gogo::message_name(package->name()).c_str(), | |
2235 | Gogo::message_name(id).c_str()); | |
2236 | return Expression::make_error(location); | |
2237 | } | |
2238 | ||
2239 | ||
2240 | if (named_object == NULL) | |
2241 | { | |
2242 | if (package != NULL) | |
2243 | { | |
2244 | std::string n1 = Gogo::message_name(package->name()); | |
2245 | std::string n2 = Gogo::message_name(id); | |
2246 | if (!is_exported) | |
2247 | error_at(location, | |
2248 | ("invalid reference to unexported identifier " | |
2249 | "%<%s.%s%>"), | |
2250 | n1.c_str(), n2.c_str()); | |
2251 | else | |
2252 | error_at(location, | |
2253 | "reference to undefined identifier %<%s.%s%>", | |
2254 | n1.c_str(), n2.c_str()); | |
2255 | return Expression::make_error(location); | |
2256 | } | |
2257 | ||
2258 | named_object = this->gogo_->add_unknown_name(packed, location); | |
2259 | } | |
2260 | ||
2261 | if (in_function != NULL | |
2262 | && in_function != this->gogo_->current_function() | |
2263 | && (named_object->is_variable() | |
2264 | || named_object->is_result_variable())) | |
2265 | return this->enclosing_var_reference(in_function, named_object, | |
2266 | location); | |
2267 | ||
2268 | switch (named_object->classification()) | |
2269 | { | |
2270 | case Named_object::NAMED_OBJECT_CONST: | |
2271 | return Expression::make_const_reference(named_object, location); | |
2272 | case Named_object::NAMED_OBJECT_TYPE: | |
2273 | return Expression::make_type(named_object->type_value(), location); | |
2274 | case Named_object::NAMED_OBJECT_TYPE_DECLARATION: | |
2275 | { | |
2276 | Type* t = Type::make_forward_declaration(named_object); | |
2277 | return Expression::make_type(t, location); | |
2278 | } | |
2279 | case Named_object::NAMED_OBJECT_VAR: | |
2280 | case Named_object::NAMED_OBJECT_RESULT_VAR: | |
2281 | return Expression::make_var_reference(named_object, location); | |
2282 | case Named_object::NAMED_OBJECT_SINK: | |
2283 | if (may_be_sink) | |
2284 | return Expression::make_sink(location); | |
2285 | else | |
2286 | { | |
2287 | error_at(location, "cannot use _ as value"); | |
2288 | return Expression::make_error(location); | |
2289 | } | |
2290 | case Named_object::NAMED_OBJECT_FUNC: | |
2291 | case Named_object::NAMED_OBJECT_FUNC_DECLARATION: | |
2292 | return Expression::make_func_reference(named_object, NULL, | |
2293 | location); | |
2294 | case Named_object::NAMED_OBJECT_UNKNOWN: | |
2295 | return Expression::make_unknown_reference(named_object, location); | |
2296 | default: | |
2297 | gcc_unreachable(); | |
2298 | } | |
2299 | } | |
2300 | gcc_unreachable(); | |
2301 | ||
2302 | case Token::TOKEN_STRING: | |
2303 | ret = Expression::make_string(token->string_value(), token->location()); | |
2304 | this->advance_token(); | |
2305 | return ret; | |
2306 | ||
2307 | case Token::TOKEN_INTEGER: | |
2308 | ret = Expression::make_integer(token->integer_value(), NULL, | |
2309 | token->location()); | |
2310 | this->advance_token(); | |
2311 | return ret; | |
2312 | ||
2313 | case Token::TOKEN_FLOAT: | |
2314 | ret = Expression::make_float(token->float_value(), NULL, | |
2315 | token->location()); | |
2316 | this->advance_token(); | |
2317 | return ret; | |
2318 | ||
2319 | case Token::TOKEN_IMAGINARY: | |
2320 | { | |
2321 | mpfr_t zero; | |
2322 | mpfr_init_set_ui(zero, 0, GMP_RNDN); | |
2323 | ret = Expression::make_complex(&zero, token->imaginary_value(), | |
2324 | NULL, token->location()); | |
2325 | mpfr_clear(zero); | |
2326 | this->advance_token(); | |
2327 | return ret; | |
2328 | } | |
2329 | ||
2330 | case Token::TOKEN_KEYWORD: | |
2331 | switch (token->keyword()) | |
2332 | { | |
2333 | case KEYWORD_FUNC: | |
2334 | return this->function_lit(); | |
2335 | case KEYWORD_CHAN: | |
2336 | case KEYWORD_INTERFACE: | |
2337 | case KEYWORD_MAP: | |
2338 | case KEYWORD_STRUCT: | |
2339 | { | |
2340 | source_location location = token->location(); | |
2341 | return Expression::make_type(this->type(), location); | |
2342 | } | |
2343 | default: | |
2344 | break; | |
2345 | } | |
2346 | break; | |
2347 | ||
2348 | case Token::TOKEN_OPERATOR: | |
2349 | if (token->is_op(OPERATOR_LPAREN)) | |
2350 | { | |
2351 | this->advance_token(); | |
2352 | ret = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
2353 | if (!this->peek_token()->is_op(OPERATOR_RPAREN)) | |
2354 | error_at(this->location(), "missing %<)%>"); | |
2355 | else | |
2356 | this->advance_token(); | |
2357 | return ret; | |
2358 | } | |
2359 | else if (token->is_op(OPERATOR_LSQUARE)) | |
2360 | { | |
2361 | // Here we call array_type directly, as this is the only | |
2362 | // case where an ellipsis is permitted for an array type. | |
2363 | source_location location = token->location(); | |
2364 | return Expression::make_type(this->array_type(true), location); | |
2365 | } | |
2366 | break; | |
2367 | ||
2368 | default: | |
2369 | break; | |
2370 | } | |
2371 | ||
2372 | error_at(this->location(), "expected operand"); | |
2373 | return Expression::make_error(this->location()); | |
2374 | } | |
2375 | ||
2376 | // Handle a reference to a variable in an enclosing function. We add | |
2377 | // it to a list of such variables. We return a reference to a field | |
2378 | // in a struct which will be passed on the static chain when calling | |
2379 | // the current function. | |
2380 | ||
2381 | Expression* | |
2382 | Parse::enclosing_var_reference(Named_object* in_function, Named_object* var, | |
2383 | source_location location) | |
2384 | { | |
2385 | gcc_assert(var->is_variable() || var->is_result_variable()); | |
2386 | ||
2387 | Named_object* this_function = this->gogo_->current_function(); | |
2388 | Named_object* closure = this_function->func_value()->closure_var(); | |
2389 | ||
2390 | Enclosing_var ev(var, in_function, this->enclosing_vars_.size()); | |
2391 | std::pair<Enclosing_vars::iterator, bool> ins = | |
2392 | this->enclosing_vars_.insert(ev); | |
2393 | if (ins.second) | |
2394 | { | |
2395 | // This is a variable we have not seen before. Add a new field | |
2396 | // to the closure type. | |
2397 | this_function->func_value()->add_closure_field(var, location); | |
2398 | } | |
2399 | ||
2400 | Expression* closure_ref = Expression::make_var_reference(closure, | |
2401 | location); | |
2402 | closure_ref = Expression::make_unary(OPERATOR_MULT, closure_ref, location); | |
2403 | ||
2404 | // The closure structure holds pointers to the variables, so we need | |
2405 | // to introduce an indirection. | |
2406 | Expression* e = Expression::make_field_reference(closure_ref, | |
2407 | ins.first->index(), | |
2408 | location); | |
2409 | e = Expression::make_unary(OPERATOR_MULT, e, location); | |
2410 | return e; | |
2411 | } | |
2412 | ||
2413 | // CompositeLit = LiteralType LiteralValue . | |
2414 | // LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | | |
2415 | // SliceType | MapType | TypeName . | |
2416 | // LiteralValue = "{" [ ElementList [ "," ] ] "}" . | |
2417 | // ElementList = Element { "," Element } . | |
2418 | // Element = [ Key ":" ] Value . | |
2419 | // Key = Expression . | |
2420 | // Value = Expression | LiteralValue . | |
2421 | ||
2422 | // We have already seen the type if there is one, and we are now | |
2423 | // looking at the LiteralValue. The case "[" "..." "]" ElementType | |
2424 | // will be seen here as an array type whose length is "nil". The | |
2425 | // DEPTH parameter is non-zero if this is an embedded composite | |
2426 | // literal and the type was omitted. It gives the number of steps up | |
2427 | // to the type which was provided. E.g., in [][]int{{1}} it will be | |
2428 | // 1. In [][][]int{{{1}}} it will be 2. | |
2429 | ||
2430 | Expression* | |
2431 | Parse::composite_lit(Type* type, int depth, source_location location) | |
2432 | { | |
2433 | gcc_assert(this->peek_token()->is_op(OPERATOR_LCURLY)); | |
2434 | this->advance_token(); | |
2435 | ||
2436 | if (this->peek_token()->is_op(OPERATOR_RCURLY)) | |
2437 | { | |
2438 | this->advance_token(); | |
2439 | return Expression::make_composite_literal(type, depth, false, NULL, | |
2440 | location); | |
2441 | } | |
2442 | ||
2443 | bool has_keys = false; | |
2444 | Expression_list* vals = new Expression_list; | |
2445 | while (true) | |
2446 | { | |
2447 | Expression* val; | |
2448 | bool is_type_omitted = false; | |
2449 | ||
2450 | const Token* token = this->peek_token(); | |
2451 | ||
2452 | if (!token->is_op(OPERATOR_LCURLY)) | |
2453 | val = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
2454 | else | |
2455 | { | |
2456 | // This must be a composite literal inside another composite | |
2457 | // literal, with the type omitted for the inner one. | |
2458 | val = this->composite_lit(type, depth + 1, token->location()); | |
2459 | is_type_omitted = true; | |
2460 | } | |
2461 | ||
2462 | token = this->peek_token(); | |
2463 | if (!token->is_op(OPERATOR_COLON)) | |
2464 | { | |
2465 | if (has_keys) | |
2466 | vals->push_back(NULL); | |
2467 | } | |
2468 | else | |
2469 | { | |
2470 | if (is_type_omitted && !val->is_error_expression()) | |
2471 | { | |
2472 | error_at(this->location(), "unexpected %<:%>"); | |
2473 | val = Expression::make_error(this->location()); | |
2474 | } | |
2475 | ||
2476 | this->advance_token(); | |
2477 | ||
2478 | if (!has_keys && !vals->empty()) | |
2479 | { | |
2480 | Expression_list* newvals = new Expression_list; | |
2481 | for (Expression_list::const_iterator p = vals->begin(); | |
2482 | p != vals->end(); | |
2483 | ++p) | |
2484 | { | |
2485 | newvals->push_back(NULL); | |
2486 | newvals->push_back(*p); | |
2487 | } | |
2488 | delete vals; | |
2489 | vals = newvals; | |
2490 | } | |
2491 | has_keys = true; | |
2492 | ||
2493 | if (val->unknown_expression() != NULL) | |
2494 | val->unknown_expression()->set_is_composite_literal_key(); | |
2495 | ||
2496 | vals->push_back(val); | |
2497 | ||
2498 | if (!token->is_op(OPERATOR_LCURLY)) | |
2499 | val = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
2500 | else | |
2501 | { | |
2502 | // This must be a composite literal inside another | |
2503 | // composite literal, with the type omitted for the | |
2504 | // inner one. | |
2505 | val = this->composite_lit(type, depth + 1, token->location()); | |
2506 | } | |
2507 | ||
2508 | token = this->peek_token(); | |
2509 | } | |
2510 | ||
2511 | vals->push_back(val); | |
2512 | ||
2513 | if (token->is_op(OPERATOR_COMMA)) | |
2514 | { | |
2515 | if (this->advance_token()->is_op(OPERATOR_RCURLY)) | |
2516 | { | |
2517 | this->advance_token(); | |
2518 | break; | |
2519 | } | |
2520 | } | |
2521 | else if (token->is_op(OPERATOR_RCURLY)) | |
2522 | { | |
2523 | this->advance_token(); | |
2524 | break; | |
2525 | } | |
2526 | else | |
2527 | { | |
2528 | error_at(this->location(), "expected %<,%> or %<}%>"); | |
2529 | ||
2530 | int depth = 0; | |
2531 | while (!token->is_eof() | |
2532 | && (depth > 0 || !token->is_op(OPERATOR_RCURLY))) | |
2533 | { | |
2534 | if (token->is_op(OPERATOR_LCURLY)) | |
2535 | ++depth; | |
2536 | else if (token->is_op(OPERATOR_RCURLY)) | |
2537 | --depth; | |
2538 | token = this->advance_token(); | |
2539 | } | |
2540 | if (token->is_op(OPERATOR_RCURLY)) | |
2541 | this->advance_token(); | |
2542 | ||
2543 | return Expression::make_error(location); | |
2544 | } | |
2545 | } | |
2546 | ||
2547 | return Expression::make_composite_literal(type, depth, has_keys, vals, | |
2548 | location); | |
2549 | } | |
2550 | ||
2551 | // FunctionLit = "func" Signature Block . | |
2552 | ||
2553 | Expression* | |
2554 | Parse::function_lit() | |
2555 | { | |
2556 | source_location location = this->location(); | |
2557 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_FUNC)); | |
2558 | this->advance_token(); | |
2559 | ||
2560 | Enclosing_vars hold_enclosing_vars; | |
2561 | hold_enclosing_vars.swap(this->enclosing_vars_); | |
2562 | ||
2563 | Function_type* type = this->signature(NULL, location); | |
cad51bed | 2564 | if (type == NULL) |
73487f1e | 2565 | type = Type::make_function_type(NULL, NULL, NULL, location); |
7a938933 ILT |
2566 | |
2567 | // For a function literal, the next token must be a '{'. If we | |
2568 | // don't see that, then we may have a type expression. | |
2569 | if (!this->peek_token()->is_op(OPERATOR_LCURLY)) | |
2570 | return Expression::make_type(type, location); | |
2571 | ||
bdc4349d ILT |
2572 | Bc_stack* hold_break_stack = this->break_stack_; |
2573 | Bc_stack* hold_continue_stack = this->continue_stack_; | |
2574 | this->break_stack_ = NULL; | |
2575 | this->continue_stack_ = NULL; | |
2576 | ||
7a938933 ILT |
2577 | Named_object* no = this->gogo_->start_function("", type, true, location); |
2578 | ||
2579 | source_location end_loc = this->block(); | |
2580 | ||
2581 | this->gogo_->finish_function(end_loc); | |
2582 | ||
bdc4349d ILT |
2583 | if (this->break_stack_ != NULL) |
2584 | delete this->break_stack_; | |
2585 | if (this->continue_stack_ != NULL) | |
2586 | delete this->continue_stack_; | |
2587 | this->break_stack_ = hold_break_stack; | |
2588 | this->continue_stack_ = hold_continue_stack; | |
2589 | ||
7a938933 ILT |
2590 | hold_enclosing_vars.swap(this->enclosing_vars_); |
2591 | ||
2592 | Expression* closure = this->create_closure(no, &hold_enclosing_vars, | |
2593 | location); | |
2594 | ||
2595 | return Expression::make_func_reference(no, closure, location); | |
2596 | } | |
2597 | ||
2598 | // Create a closure for the nested function FUNCTION. This is based | |
2599 | // on ENCLOSING_VARS, which is a list of all variables defined in | |
2600 | // enclosing functions and referenced from FUNCTION. A closure is the | |
2601 | // address of a struct which contains the addresses of all the | |
2602 | // referenced variables. This returns NULL if no closure is required. | |
2603 | ||
2604 | Expression* | |
2605 | Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars, | |
2606 | source_location location) | |
2607 | { | |
2608 | if (enclosing_vars->empty()) | |
2609 | return NULL; | |
2610 | ||
2611 | // Get the variables in order by their field index. | |
2612 | ||
2613 | size_t enclosing_var_count = enclosing_vars->size(); | |
2614 | std::vector<Enclosing_var> ev(enclosing_var_count); | |
2615 | for (Enclosing_vars::const_iterator p = enclosing_vars->begin(); | |
2616 | p != enclosing_vars->end(); | |
2617 | ++p) | |
2618 | ev[p->index()] = *p; | |
2619 | ||
2620 | // Build an initializer for a composite literal of the closure's | |
2621 | // type. | |
2622 | ||
2623 | Named_object* enclosing_function = this->gogo_->current_function(); | |
2624 | Expression_list* initializer = new Expression_list; | |
2625 | for (size_t i = 0; i < enclosing_var_count; ++i) | |
2626 | { | |
2627 | gcc_assert(ev[i].index() == i); | |
2628 | Named_object* var = ev[i].var(); | |
2629 | Expression* ref; | |
2630 | if (ev[i].in_function() == enclosing_function) | |
2631 | ref = Expression::make_var_reference(var, location); | |
2632 | else | |
2633 | ref = this->enclosing_var_reference(ev[i].in_function(), var, | |
2634 | location); | |
2635 | Expression* refaddr = Expression::make_unary(OPERATOR_AND, ref, | |
2636 | location); | |
2637 | initializer->push_back(refaddr); | |
2638 | } | |
2639 | ||
2640 | Named_object* closure_var = function->func_value()->closure_var(); | |
2641 | Struct_type* st = closure_var->var_value()->type()->deref()->struct_type(); | |
2642 | Expression* cv = Expression::make_struct_composite_literal(st, initializer, | |
2643 | location); | |
2644 | return Expression::make_heap_composite(cv, location); | |
2645 | } | |
2646 | ||
2647 | // PrimaryExpr = Operand { Selector | Index | Slice | TypeGuard | Call } . | |
2648 | ||
2649 | // If MAY_BE_SINK is true, this expression may be "_". | |
2650 | ||
2651 | // If MAY_BE_COMPOSITE_LIT is true, this expression may be a composite | |
2652 | // literal. | |
2653 | ||
2654 | // If IS_TYPE_SWITCH is not NULL, this will recognize a type switch | |
2655 | // guard (var := expr.("type") using the literal keyword "type"). | |
2656 | ||
2657 | Expression* | |
2658 | Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit, | |
2659 | bool* is_type_switch) | |
2660 | { | |
2661 | source_location start_loc = this->location(); | |
2662 | bool is_parenthesized = this->peek_token()->is_op(OPERATOR_LPAREN); | |
2663 | ||
2664 | Expression* ret = this->operand(may_be_sink); | |
2665 | ||
2666 | // An unknown name followed by a curly brace must be a composite | |
2667 | // literal, and the unknown name must be a type. | |
2668 | if (may_be_composite_lit | |
2669 | && !is_parenthesized | |
2670 | && ret->unknown_expression() != NULL | |
2671 | && this->peek_token()->is_op(OPERATOR_LCURLY)) | |
2672 | { | |
2673 | Named_object* no = ret->unknown_expression()->named_object(); | |
2674 | Type* type = Type::make_forward_declaration(no); | |
2675 | ret = Expression::make_type(type, ret->location()); | |
2676 | } | |
2677 | ||
2678 | // We handle composite literals and type casts here, as it is the | |
2679 | // easiest way to handle types which are in parentheses, as in | |
2680 | // "((uint))(1)". | |
2681 | if (ret->is_type_expression()) | |
2682 | { | |
2683 | if (this->peek_token()->is_op(OPERATOR_LCURLY)) | |
2684 | { | |
2685 | if (is_parenthesized) | |
2686 | error_at(start_loc, | |
2687 | "cannot parenthesize type in composite literal"); | |
2688 | ret = this->composite_lit(ret->type(), 0, ret->location()); | |
2689 | } | |
2690 | else if (this->peek_token()->is_op(OPERATOR_LPAREN)) | |
2691 | { | |
2692 | source_location loc = this->location(); | |
2693 | this->advance_token(); | |
2694 | Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, | |
2695 | NULL); | |
2696 | if (!this->peek_token()->is_op(OPERATOR_RPAREN)) | |
2697 | error_at(this->location(), "expected %<)%>"); | |
2698 | else | |
2699 | this->advance_token(); | |
2700 | if (expr->is_error_expression()) | |
2701 | return expr; | |
2702 | ret = Expression::make_cast(ret->type(), expr, loc); | |
2703 | } | |
2704 | } | |
2705 | ||
2706 | while (true) | |
2707 | { | |
2708 | const Token* token = this->peek_token(); | |
2709 | if (token->is_op(OPERATOR_LPAREN)) | |
2710 | ret = this->call(this->verify_not_sink(ret)); | |
2711 | else if (token->is_op(OPERATOR_DOT)) | |
2712 | { | |
2713 | ret = this->selector(this->verify_not_sink(ret), is_type_switch); | |
2714 | if (is_type_switch != NULL && *is_type_switch) | |
2715 | break; | |
2716 | } | |
2717 | else if (token->is_op(OPERATOR_LSQUARE)) | |
2718 | ret = this->index(this->verify_not_sink(ret)); | |
2719 | else | |
2720 | break; | |
2721 | } | |
2722 | ||
2723 | return ret; | |
2724 | } | |
2725 | ||
2726 | // Selector = "." identifier . | |
2727 | // TypeGuard = "." "(" QualifiedIdent ")" . | |
2728 | ||
2729 | // Note that Operand can expand to QualifiedIdent, which contains a | |
2730 | // ".". That is handled directly in operand when it sees a package | |
2731 | // name. | |
2732 | ||
2733 | // If IS_TYPE_SWITCH is not NULL, this will recognize a type switch | |
2734 | // guard (var := expr.("type") using the literal keyword "type"). | |
2735 | ||
2736 | Expression* | |
2737 | Parse::selector(Expression* left, bool* is_type_switch) | |
2738 | { | |
2739 | gcc_assert(this->peek_token()->is_op(OPERATOR_DOT)); | |
2740 | source_location location = this->location(); | |
2741 | ||
2742 | const Token* token = this->advance_token(); | |
2743 | if (token->is_identifier()) | |
2744 | { | |
2745 | // This could be a field in a struct, or a method in an | |
2746 | // interface, or a method associated with a type. We can't know | |
2747 | // which until we have seen all the types. | |
2748 | std::string name = | |
2749 | this->gogo_->pack_hidden_name(token->identifier(), | |
2750 | token->is_identifier_exported()); | |
2751 | if (token->identifier() == "_") | |
2752 | { | |
2753 | error_at(this->location(), "invalid use of %<_%>"); | |
2754 | name = this->gogo_->pack_hidden_name("blank", false); | |
2755 | } | |
2756 | this->advance_token(); | |
2757 | return Expression::make_selector(left, name, location); | |
2758 | } | |
2759 | else if (token->is_op(OPERATOR_LPAREN)) | |
2760 | { | |
2761 | this->advance_token(); | |
2762 | Type* type = NULL; | |
05d556e8 | 2763 | if (!this->peek_token()->is_keyword(KEYWORD_TYPE)) |
7a938933 ILT |
2764 | type = this->type(); |
2765 | else | |
2766 | { | |
05d556e8 ILT |
2767 | if (is_type_switch != NULL) |
2768 | *is_type_switch = true; | |
2769 | else | |
2770 | { | |
2771 | error_at(this->location(), | |
2772 | "use of %<.(type)%> outside type switch"); | |
2773 | type = Type::make_error_type(); | |
2774 | } | |
7a938933 ILT |
2775 | this->advance_token(); |
2776 | } | |
2777 | if (!this->peek_token()->is_op(OPERATOR_RPAREN)) | |
2778 | error_at(this->location(), "missing %<)%>"); | |
2779 | else | |
2780 | this->advance_token(); | |
2781 | if (is_type_switch != NULL && *is_type_switch) | |
2782 | return left; | |
2783 | return Expression::make_type_guard(left, type, location); | |
2784 | } | |
2785 | else | |
2786 | { | |
2787 | error_at(this->location(), "expected identifier or %<(%>"); | |
2788 | return left; | |
2789 | } | |
2790 | } | |
2791 | ||
2792 | // Index = "[" Expression "]" . | |
2793 | // Slice = "[" Expression ":" [ Expression ] "]" . | |
2794 | ||
2795 | Expression* | |
2796 | Parse::index(Expression* expr) | |
2797 | { | |
2798 | source_location location = this->location(); | |
2799 | gcc_assert(this->peek_token()->is_op(OPERATOR_LSQUARE)); | |
2800 | this->advance_token(); | |
2801 | ||
2802 | Expression* start; | |
2803 | if (!this->peek_token()->is_op(OPERATOR_COLON)) | |
2804 | start = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
2805 | else | |
2806 | { | |
2807 | mpz_t zero; | |
2808 | mpz_init_set_ui(zero, 0); | |
2809 | start = Expression::make_integer(&zero, NULL, location); | |
2810 | mpz_clear(zero); | |
2811 | } | |
2812 | ||
2813 | Expression* end = NULL; | |
2814 | if (this->peek_token()->is_op(OPERATOR_COLON)) | |
2815 | { | |
2816 | // We use nil to indicate a missing high expression. | |
2817 | if (this->advance_token()->is_op(OPERATOR_RSQUARE)) | |
2818 | end = Expression::make_nil(this->location()); | |
2819 | else | |
2820 | end = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
2821 | } | |
2822 | if (!this->peek_token()->is_op(OPERATOR_RSQUARE)) | |
2823 | error_at(this->location(), "missing %<]%>"); | |
2824 | else | |
2825 | this->advance_token(); | |
2826 | return Expression::make_index(expr, start, end, location); | |
2827 | } | |
2828 | ||
2829 | // Call = "(" [ ArgumentList [ "," ] ] ")" . | |
2830 | // ArgumentList = ExpressionList [ "..." ] . | |
2831 | ||
2832 | Expression* | |
2833 | Parse::call(Expression* func) | |
2834 | { | |
2835 | gcc_assert(this->peek_token()->is_op(OPERATOR_LPAREN)); | |
2836 | Expression_list* args = NULL; | |
2837 | bool is_varargs = false; | |
2838 | const Token* token = this->advance_token(); | |
2839 | if (!token->is_op(OPERATOR_RPAREN)) | |
2840 | { | |
2841 | args = this->expression_list(NULL, false); | |
2842 | token = this->peek_token(); | |
2843 | if (token->is_op(OPERATOR_ELLIPSIS)) | |
2844 | { | |
2845 | is_varargs = true; | |
2846 | token = this->advance_token(); | |
2847 | } | |
2848 | } | |
2849 | if (token->is_op(OPERATOR_COMMA)) | |
2850 | token = this->advance_token(); | |
2851 | if (!token->is_op(OPERATOR_RPAREN)) | |
2852 | error_at(this->location(), "missing %<)%>"); | |
2853 | else | |
2854 | this->advance_token(); | |
2855 | if (func->is_error_expression()) | |
2856 | return func; | |
2857 | return Expression::make_call(func, args, is_varargs, func->location()); | |
2858 | } | |
2859 | ||
2860 | // Return an expression for a single unqualified identifier. | |
2861 | ||
2862 | Expression* | |
2863 | Parse::id_to_expression(const std::string& name, source_location location) | |
2864 | { | |
2865 | Named_object* in_function; | |
2866 | Named_object* named_object = this->gogo_->lookup(name, &in_function); | |
2867 | if (named_object == NULL) | |
2868 | named_object = this->gogo_->add_unknown_name(name, location); | |
2869 | ||
2870 | if (in_function != NULL | |
2871 | && in_function != this->gogo_->current_function() | |
2872 | && (named_object->is_variable() || named_object->is_result_variable())) | |
2873 | return this->enclosing_var_reference(in_function, named_object, | |
2874 | location); | |
2875 | ||
2876 | switch (named_object->classification()) | |
2877 | { | |
2878 | case Named_object::NAMED_OBJECT_CONST: | |
2879 | return Expression::make_const_reference(named_object, location); | |
2880 | case Named_object::NAMED_OBJECT_VAR: | |
2881 | case Named_object::NAMED_OBJECT_RESULT_VAR: | |
2882 | return Expression::make_var_reference(named_object, location); | |
2883 | case Named_object::NAMED_OBJECT_SINK: | |
2884 | return Expression::make_sink(location); | |
2885 | case Named_object::NAMED_OBJECT_FUNC: | |
2886 | case Named_object::NAMED_OBJECT_FUNC_DECLARATION: | |
2887 | return Expression::make_func_reference(named_object, NULL, location); | |
2888 | case Named_object::NAMED_OBJECT_UNKNOWN: | |
2889 | return Expression::make_unknown_reference(named_object, location); | |
2890 | default: | |
2891 | error_at(this->location(), "unexpected type of identifier"); | |
2892 | return Expression::make_error(location); | |
2893 | } | |
2894 | } | |
2895 | ||
2896 | // Expression = UnaryExpr { binary_op Expression } . | |
2897 | ||
2898 | // PRECEDENCE is the precedence of the current operator. | |
2899 | ||
2900 | // If MAY_BE_SINK is true, this expression may be "_". | |
2901 | ||
2902 | // If MAY_BE_COMPOSITE_LIT is true, this expression may be a composite | |
2903 | // literal. | |
2904 | ||
2905 | // If IS_TYPE_SWITCH is not NULL, this will recognize a type switch | |
2906 | // guard (var := expr.("type") using the literal keyword "type"). | |
2907 | ||
2908 | Expression* | |
2909 | Parse::expression(Precedence precedence, bool may_be_sink, | |
2910 | bool may_be_composite_lit, bool* is_type_switch) | |
2911 | { | |
2912 | Expression* left = this->unary_expr(may_be_sink, may_be_composite_lit, | |
2913 | is_type_switch); | |
2914 | ||
2915 | while (true) | |
2916 | { | |
2917 | if (is_type_switch != NULL && *is_type_switch) | |
2918 | return left; | |
2919 | ||
2920 | const Token* token = this->peek_token(); | |
2921 | if (token->classification() != Token::TOKEN_OPERATOR) | |
2922 | { | |
2923 | // Not a binary_op. | |
2924 | return left; | |
2925 | } | |
2926 | ||
2927 | Precedence right_precedence; | |
2928 | switch (token->op()) | |
2929 | { | |
2930 | case OPERATOR_OROR: | |
2931 | right_precedence = PRECEDENCE_OROR; | |
2932 | break; | |
2933 | case OPERATOR_ANDAND: | |
2934 | right_precedence = PRECEDENCE_ANDAND; | |
2935 | break; | |
2936 | case OPERATOR_CHANOP: | |
2937 | right_precedence = PRECEDENCE_CHANOP; | |
2938 | break; | |
2939 | case OPERATOR_EQEQ: | |
2940 | case OPERATOR_NOTEQ: | |
2941 | case OPERATOR_LT: | |
2942 | case OPERATOR_LE: | |
2943 | case OPERATOR_GT: | |
2944 | case OPERATOR_GE: | |
2945 | right_precedence = PRECEDENCE_RELOP; | |
2946 | break; | |
2947 | case OPERATOR_PLUS: | |
2948 | case OPERATOR_MINUS: | |
2949 | case OPERATOR_OR: | |
2950 | case OPERATOR_XOR: | |
2951 | right_precedence = PRECEDENCE_ADDOP; | |
2952 | break; | |
2953 | case OPERATOR_MULT: | |
2954 | case OPERATOR_DIV: | |
2955 | case OPERATOR_MOD: | |
2956 | case OPERATOR_LSHIFT: | |
2957 | case OPERATOR_RSHIFT: | |
2958 | case OPERATOR_AND: | |
2959 | case OPERATOR_BITCLEAR: | |
2960 | right_precedence = PRECEDENCE_MULOP; | |
2961 | break; | |
2962 | default: | |
2963 | right_precedence = PRECEDENCE_INVALID; | |
2964 | break; | |
2965 | } | |
2966 | ||
2967 | if (right_precedence == PRECEDENCE_INVALID) | |
2968 | { | |
2969 | // Not a binary_op. | |
2970 | return left; | |
2971 | } | |
2972 | ||
2973 | Operator op = token->op(); | |
2974 | source_location binop_location = token->location(); | |
2975 | ||
2976 | if (precedence >= right_precedence) | |
2977 | { | |
2978 | // We've already seen A * B, and we see + C. We want to | |
2979 | // return so that A * B becomes a group. | |
2980 | return left; | |
2981 | } | |
2982 | ||
2983 | this->advance_token(); | |
2984 | ||
2985 | left = this->verify_not_sink(left); | |
2986 | Expression* right = this->expression(right_precedence, false, | |
2987 | may_be_composite_lit, | |
05d556e8 | 2988 | NULL); |
7a938933 ILT |
2989 | if (op == OPERATOR_CHANOP) |
2990 | left = Expression::make_send(left, right, binop_location); | |
2991 | else | |
2992 | left = Expression::make_binary(op, left, right, binop_location); | |
2993 | } | |
2994 | } | |
2995 | ||
2996 | bool | |
2997 | Parse::expression_may_start_here() | |
2998 | { | |
2999 | const Token* token = this->peek_token(); | |
3000 | switch (token->classification()) | |
3001 | { | |
3002 | case Token::TOKEN_INVALID: | |
3003 | case Token::TOKEN_EOF: | |
3004 | return false; | |
3005 | case Token::TOKEN_KEYWORD: | |
3006 | switch (token->keyword()) | |
3007 | { | |
3008 | case KEYWORD_CHAN: | |
3009 | case KEYWORD_FUNC: | |
3010 | case KEYWORD_MAP: | |
3011 | case KEYWORD_STRUCT: | |
3012 | case KEYWORD_INTERFACE: | |
3013 | return true; | |
3014 | default: | |
3015 | return false; | |
3016 | } | |
3017 | case Token::TOKEN_IDENTIFIER: | |
3018 | return true; | |
3019 | case Token::TOKEN_STRING: | |
3020 | return true; | |
3021 | case Token::TOKEN_OPERATOR: | |
3022 | switch (token->op()) | |
3023 | { | |
3024 | case OPERATOR_PLUS: | |
3025 | case OPERATOR_MINUS: | |
3026 | case OPERATOR_NOT: | |
3027 | case OPERATOR_XOR: | |
3028 | case OPERATOR_MULT: | |
3029 | case OPERATOR_CHANOP: | |
3030 | case OPERATOR_AND: | |
3031 | case OPERATOR_LPAREN: | |
3032 | case OPERATOR_LSQUARE: | |
3033 | return true; | |
3034 | default: | |
3035 | return false; | |
3036 | } | |
3037 | case Token::TOKEN_INTEGER: | |
3038 | case Token::TOKEN_FLOAT: | |
3039 | case Token::TOKEN_IMAGINARY: | |
3040 | return true; | |
3041 | default: | |
3042 | gcc_unreachable(); | |
3043 | } | |
3044 | } | |
3045 | ||
3046 | // UnaryExpr = unary_op UnaryExpr | PrimaryExpr . | |
3047 | ||
3048 | // If MAY_BE_SINK is true, this expression may be "_". | |
3049 | ||
3050 | // If MAY_BE_COMPOSITE_LIT is true, this expression may be a composite | |
3051 | // literal. | |
3052 | ||
3053 | // If IS_TYPE_SWITCH is not NULL, this will recognize a type switch | |
3054 | // guard (var := expr.("type") using the literal keyword "type"). | |
3055 | ||
3056 | Expression* | |
3057 | Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit, | |
3058 | bool* is_type_switch) | |
3059 | { | |
3060 | const Token* token = this->peek_token(); | |
3061 | if (token->is_op(OPERATOR_PLUS) | |
3062 | || token->is_op(OPERATOR_MINUS) | |
3063 | || token->is_op(OPERATOR_NOT) | |
3064 | || token->is_op(OPERATOR_XOR) | |
3065 | || token->is_op(OPERATOR_CHANOP) | |
3066 | || token->is_op(OPERATOR_MULT) | |
3067 | || token->is_op(OPERATOR_AND)) | |
3068 | { | |
3069 | source_location location = token->location(); | |
3070 | Operator op = token->op(); | |
3071 | this->advance_token(); | |
3072 | ||
3073 | if (op == OPERATOR_CHANOP | |
3074 | && this->peek_token()->is_keyword(KEYWORD_CHAN)) | |
3075 | { | |
3076 | // This is "<- chan" which must be the start of a type. | |
3077 | this->unget_token(Token::make_operator_token(op, location)); | |
3078 | return Expression::make_type(this->type(), location); | |
3079 | } | |
3080 | ||
05d556e8 | 3081 | Expression* expr = this->unary_expr(false, may_be_composite_lit, NULL); |
7a938933 ILT |
3082 | if (expr->is_error_expression()) |
3083 | ; | |
3084 | else if (op == OPERATOR_MULT && expr->is_type_expression()) | |
3085 | expr = Expression::make_type(Type::make_pointer_type(expr->type()), | |
3086 | location); | |
3087 | else if (op == OPERATOR_AND && expr->is_composite_literal()) | |
3088 | expr = Expression::make_heap_composite(expr, location); | |
3089 | else if (op != OPERATOR_CHANOP) | |
3090 | expr = Expression::make_unary(op, expr, location); | |
3091 | else | |
3092 | expr = Expression::make_receive(expr, location); | |
3093 | return expr; | |
3094 | } | |
3095 | else | |
3096 | return this->primary_expr(may_be_sink, may_be_composite_lit, | |
3097 | is_type_switch); | |
3098 | } | |
3099 | ||
3100 | // Statement = | |
3101 | // Declaration | LabeledStmt | SimpleStmt | | |
3102 | // GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | | |
3103 | // FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | | |
3104 | // DeferStmt . | |
3105 | ||
3106 | // LABEL is the label of this statement if it has one. | |
3107 | ||
3108 | void | |
3109 | Parse::statement(const Label* label) | |
3110 | { | |
3111 | const Token* token = this->peek_token(); | |
3112 | switch (token->classification()) | |
3113 | { | |
3114 | case Token::TOKEN_KEYWORD: | |
3115 | { | |
3116 | switch (token->keyword()) | |
3117 | { | |
3118 | case KEYWORD_CONST: | |
3119 | case KEYWORD_TYPE: | |
3120 | case KEYWORD_VAR: | |
3121 | this->declaration(); | |
3122 | break; | |
3123 | case KEYWORD_FUNC: | |
3124 | case KEYWORD_MAP: | |
3125 | case KEYWORD_STRUCT: | |
3126 | case KEYWORD_INTERFACE: | |
3127 | this->simple_stat(true, false, NULL, NULL); | |
3128 | break; | |
3129 | case KEYWORD_GO: | |
3130 | case KEYWORD_DEFER: | |
3131 | this->go_or_defer_stat(); | |
3132 | break; | |
3133 | case KEYWORD_RETURN: | |
3134 | this->return_stat(); | |
3135 | break; | |
3136 | case KEYWORD_BREAK: | |
3137 | this->break_stat(); | |
3138 | break; | |
3139 | case KEYWORD_CONTINUE: | |
3140 | this->continue_stat(); | |
3141 | break; | |
3142 | case KEYWORD_GOTO: | |
3143 | this->goto_stat(); | |
3144 | break; | |
3145 | case KEYWORD_IF: | |
3146 | this->if_stat(); | |
3147 | break; | |
3148 | case KEYWORD_SWITCH: | |
3149 | this->switch_stat(label); | |
3150 | break; | |
3151 | case KEYWORD_SELECT: | |
3152 | this->select_stat(label); | |
3153 | break; | |
3154 | case KEYWORD_FOR: | |
3155 | this->for_stat(label); | |
3156 | break; | |
3157 | default: | |
3158 | error_at(this->location(), "expected statement"); | |
3159 | this->advance_token(); | |
3160 | break; | |
3161 | } | |
3162 | } | |
3163 | break; | |
3164 | ||
3165 | case Token::TOKEN_IDENTIFIER: | |
3166 | { | |
3167 | std::string identifier = token->identifier(); | |
3168 | bool is_exported = token->is_identifier_exported(); | |
3169 | source_location location = token->location(); | |
3170 | if (this->advance_token()->is_op(OPERATOR_COLON)) | |
3171 | { | |
3172 | this->advance_token(); | |
3173 | this->labeled_stmt(identifier, location); | |
3174 | } | |
3175 | else | |
3176 | { | |
3177 | this->unget_token(Token::make_identifier_token(identifier, | |
3178 | is_exported, | |
3179 | location)); | |
3180 | this->simple_stat(true, false, NULL, NULL); | |
3181 | } | |
3182 | } | |
3183 | break; | |
3184 | ||
3185 | case Token::TOKEN_OPERATOR: | |
3186 | if (token->is_op(OPERATOR_LCURLY)) | |
3187 | { | |
3188 | source_location location = token->location(); | |
3189 | this->gogo_->start_block(location); | |
3190 | source_location end_loc = this->block(); | |
3191 | this->gogo_->add_block(this->gogo_->finish_block(end_loc), | |
3192 | location); | |
3193 | } | |
3194 | else if (!token->is_op(OPERATOR_SEMICOLON)) | |
3195 | this->simple_stat(true, false, NULL, NULL); | |
3196 | break; | |
3197 | ||
3198 | case Token::TOKEN_STRING: | |
3199 | case Token::TOKEN_INTEGER: | |
3200 | case Token::TOKEN_FLOAT: | |
3201 | case Token::TOKEN_IMAGINARY: | |
3202 | this->simple_stat(true, false, NULL, NULL); | |
3203 | break; | |
3204 | ||
3205 | default: | |
3206 | error_at(this->location(), "expected statement"); | |
3207 | this->advance_token(); | |
3208 | break; | |
3209 | } | |
3210 | } | |
3211 | ||
3212 | bool | |
3213 | Parse::statement_may_start_here() | |
3214 | { | |
3215 | const Token* token = this->peek_token(); | |
3216 | switch (token->classification()) | |
3217 | { | |
3218 | case Token::TOKEN_KEYWORD: | |
3219 | { | |
3220 | switch (token->keyword()) | |
3221 | { | |
3222 | case KEYWORD_CONST: | |
3223 | case KEYWORD_TYPE: | |
3224 | case KEYWORD_VAR: | |
3225 | case KEYWORD_FUNC: | |
3226 | case KEYWORD_MAP: | |
3227 | case KEYWORD_STRUCT: | |
3228 | case KEYWORD_INTERFACE: | |
3229 | case KEYWORD_GO: | |
3230 | case KEYWORD_DEFER: | |
3231 | case KEYWORD_RETURN: | |
3232 | case KEYWORD_BREAK: | |
3233 | case KEYWORD_CONTINUE: | |
3234 | case KEYWORD_GOTO: | |
3235 | case KEYWORD_IF: | |
3236 | case KEYWORD_SWITCH: | |
3237 | case KEYWORD_SELECT: | |
3238 | case KEYWORD_FOR: | |
3239 | return true; | |
3240 | ||
3241 | default: | |
3242 | return false; | |
3243 | } | |
3244 | } | |
3245 | break; | |
3246 | ||
3247 | case Token::TOKEN_IDENTIFIER: | |
3248 | return true; | |
3249 | ||
3250 | case Token::TOKEN_OPERATOR: | |
3251 | if (token->is_op(OPERATOR_LCURLY) | |
3252 | || token->is_op(OPERATOR_SEMICOLON)) | |
3253 | return true; | |
3254 | else | |
3255 | return this->expression_may_start_here(); | |
3256 | ||
3257 | case Token::TOKEN_STRING: | |
3258 | case Token::TOKEN_INTEGER: | |
3259 | case Token::TOKEN_FLOAT: | |
3260 | case Token::TOKEN_IMAGINARY: | |
3261 | return true; | |
3262 | ||
3263 | default: | |
3264 | return false; | |
3265 | } | |
3266 | } | |
3267 | ||
3268 | // LabeledStmt = Label ":" Statement . | |
3269 | // Label = identifier . | |
3270 | ||
3271 | void | |
3272 | Parse::labeled_stmt(const std::string& label_name, source_location location) | |
3273 | { | |
3274 | Label* label = this->gogo_->add_label_definition(label_name, location); | |
3275 | ||
3276 | if (this->peek_token()->is_op(OPERATOR_RCURLY)) | |
3277 | { | |
3278 | // This is a label at the end of a block. A program is | |
3279 | // permitted to omit a semicolon here. | |
3280 | return; | |
3281 | } | |
3282 | ||
3283 | if (!this->statement_may_start_here()) | |
3284 | { | |
3285 | error_at(location, "missing statement after label"); | |
3286 | this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON, | |
3287 | location)); | |
3288 | return; | |
3289 | } | |
3290 | ||
3291 | this->statement(label); | |
3292 | } | |
3293 | ||
3294 | // SimpleStat = | |
3295 | // ExpressionStat | IncDecStat | Assignment | SimpleVarDecl . | |
3296 | ||
3297 | // In order to make this work for if and switch statements, if | |
3298 | // RETURN_EXP is true, and we see an ExpressionStat, we return the | |
3299 | // expression rather than adding an expression statement to the | |
3300 | // current block. If we see something other than an ExpressionStat, | |
3301 | // we add the statement and return NULL. | |
3302 | ||
3303 | // If P_RANGE_CLAUSE is not NULL, then this will recognize a | |
3304 | // RangeClause. | |
3305 | ||
3306 | // If P_TYPE_SWITCH is not NULL, this will recognize a type switch | |
3307 | // guard (var := expr.("type") using the literal keyword "type"). | |
3308 | ||
3309 | Expression* | |
3310 | Parse::simple_stat(bool may_be_composite_lit, bool return_exp, | |
3311 | Range_clause* p_range_clause, Type_switch* p_type_switch) | |
3312 | { | |
3313 | const Token* token = this->peek_token(); | |
3314 | ||
3315 | // An identifier follow by := is a SimpleVarDecl. | |
3316 | if (token->is_identifier()) | |
3317 | { | |
3318 | std::string identifier = token->identifier(); | |
3319 | bool is_exported = token->is_identifier_exported(); | |
3320 | source_location location = token->location(); | |
3321 | ||
3322 | token = this->advance_token(); | |
3323 | if (token->is_op(OPERATOR_COLONEQ) | |
3324 | || token->is_op(OPERATOR_COMMA)) | |
3325 | { | |
3326 | identifier = this->gogo_->pack_hidden_name(identifier, is_exported); | |
3327 | this->simple_var_decl_or_assignment(identifier, location, | |
3328 | p_range_clause, | |
3329 | (token->is_op(OPERATOR_COLONEQ) | |
3330 | ? p_type_switch | |
3331 | : NULL)); | |
3332 | return NULL; | |
3333 | } | |
3334 | ||
3335 | this->unget_token(Token::make_identifier_token(identifier, is_exported, | |
3336 | location)); | |
3337 | } | |
3338 | ||
3339 | Expression* exp = this->expression(PRECEDENCE_NORMAL, true, | |
3340 | may_be_composite_lit, | |
3341 | (p_type_switch == NULL | |
3342 | ? NULL | |
3343 | : &p_type_switch->found)); | |
3344 | if (p_type_switch != NULL && p_type_switch->found) | |
3345 | { | |
3346 | p_type_switch->name.clear(); | |
3347 | p_type_switch->location = exp->location(); | |
3348 | p_type_switch->expr = this->verify_not_sink(exp); | |
3349 | return NULL; | |
3350 | } | |
3351 | token = this->peek_token(); | |
3352 | if (token->is_op(OPERATOR_PLUSPLUS) || token->is_op(OPERATOR_MINUSMINUS)) | |
3353 | this->inc_dec_stat(this->verify_not_sink(exp)); | |
3354 | else if (token->is_op(OPERATOR_COMMA) | |
3355 | || token->is_op(OPERATOR_EQ)) | |
3356 | this->assignment(exp, p_range_clause); | |
3357 | else if (token->is_op(OPERATOR_PLUSEQ) | |
3358 | || token->is_op(OPERATOR_MINUSEQ) | |
3359 | || token->is_op(OPERATOR_OREQ) | |
3360 | || token->is_op(OPERATOR_XOREQ) | |
3361 | || token->is_op(OPERATOR_MULTEQ) | |
3362 | || token->is_op(OPERATOR_DIVEQ) | |
3363 | || token->is_op(OPERATOR_MODEQ) | |
3364 | || token->is_op(OPERATOR_LSHIFTEQ) | |
3365 | || token->is_op(OPERATOR_RSHIFTEQ) | |
3366 | || token->is_op(OPERATOR_ANDEQ) | |
3367 | || token->is_op(OPERATOR_BITCLEAREQ)) | |
3368 | this->assignment(this->verify_not_sink(exp), p_range_clause); | |
3369 | else if (return_exp) | |
3370 | return this->verify_not_sink(exp); | |
3371 | else | |
3372 | this->expression_stat(this->verify_not_sink(exp)); | |
3373 | ||
3374 | return NULL; | |
3375 | } | |
3376 | ||
3377 | bool | |
3378 | Parse::simple_stat_may_start_here() | |
3379 | { | |
3380 | return this->expression_may_start_here(); | |
3381 | } | |
3382 | ||
3383 | // Parse { Statement ";" } which is used in a few places. The list of | |
3384 | // statements may end with a right curly brace, in which case the | |
3385 | // semicolon may be omitted. | |
3386 | ||
3387 | void | |
3388 | Parse::statement_list() | |
3389 | { | |
3390 | while (this->statement_may_start_here()) | |
3391 | { | |
3392 | this->statement(NULL); | |
3393 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
3394 | this->advance_token(); | |
3395 | else if (this->peek_token()->is_op(OPERATOR_RCURLY)) | |
3396 | break; | |
3397 | else | |
3398 | { | |
3399 | if (!this->peek_token()->is_eof() || !saw_errors()) | |
3400 | error_at(this->location(), "expected %<;%> or %<}%> or newline"); | |
3401 | if (!this->skip_past_error(OPERATOR_RCURLY)) | |
3402 | return; | |
3403 | } | |
3404 | } | |
3405 | } | |
3406 | ||
3407 | bool | |
3408 | Parse::statement_list_may_start_here() | |
3409 | { | |
3410 | return this->statement_may_start_here(); | |
3411 | } | |
3412 | ||
3413 | // ExpressionStat = Expression . | |
3414 | ||
3415 | void | |
3416 | Parse::expression_stat(Expression* exp) | |
3417 | { | |
3418 | exp->discarding_value(); | |
3419 | this->gogo_->add_statement(Statement::make_statement(exp)); | |
3420 | } | |
3421 | ||
3422 | // IncDecStat = Expression ( "++" | "--" ) . | |
3423 | ||
3424 | void | |
3425 | Parse::inc_dec_stat(Expression* exp) | |
3426 | { | |
3427 | const Token* token = this->peek_token(); | |
3428 | ||
3429 | // Lvalue maps require special handling. | |
3430 | if (exp->index_expression() != NULL) | |
3431 | exp->index_expression()->set_is_lvalue(); | |
3432 | ||
3433 | if (token->is_op(OPERATOR_PLUSPLUS)) | |
3434 | this->gogo_->add_statement(Statement::make_inc_statement(exp)); | |
3435 | else if (token->is_op(OPERATOR_MINUSMINUS)) | |
3436 | this->gogo_->add_statement(Statement::make_dec_statement(exp)); | |
3437 | else | |
3438 | gcc_unreachable(); | |
3439 | this->advance_token(); | |
3440 | } | |
3441 | ||
3442 | // Assignment = ExpressionList assign_op ExpressionList . | |
3443 | ||
3444 | // EXP is an expression that we have already parsed. | |
3445 | ||
3446 | // If RANGE_CLAUSE is not NULL, then this will recognize a | |
3447 | // RangeClause. | |
3448 | ||
3449 | void | |
3450 | Parse::assignment(Expression* expr, Range_clause* p_range_clause) | |
3451 | { | |
3452 | Expression_list* vars; | |
3453 | if (!this->peek_token()->is_op(OPERATOR_COMMA)) | |
3454 | { | |
3455 | vars = new Expression_list(); | |
3456 | vars->push_back(expr); | |
3457 | } | |
3458 | else | |
3459 | { | |
3460 | this->advance_token(); | |
3461 | vars = this->expression_list(expr, true); | |
3462 | } | |
3463 | ||
3464 | this->tuple_assignment(vars, p_range_clause); | |
3465 | } | |
3466 | ||
3467 | // An assignment statement. LHS is the list of expressions which | |
3468 | // appear on the left hand side. | |
3469 | ||
3470 | // If RANGE_CLAUSE is not NULL, then this will recognize a | |
3471 | // RangeClause. | |
3472 | ||
3473 | void | |
3474 | Parse::tuple_assignment(Expression_list* lhs, Range_clause* p_range_clause) | |
3475 | { | |
3476 | const Token* token = this->peek_token(); | |
3477 | if (!token->is_op(OPERATOR_EQ) | |
3478 | && !token->is_op(OPERATOR_PLUSEQ) | |
3479 | && !token->is_op(OPERATOR_MINUSEQ) | |
3480 | && !token->is_op(OPERATOR_OREQ) | |
3481 | && !token->is_op(OPERATOR_XOREQ) | |
3482 | && !token->is_op(OPERATOR_MULTEQ) | |
3483 | && !token->is_op(OPERATOR_DIVEQ) | |
3484 | && !token->is_op(OPERATOR_MODEQ) | |
3485 | && !token->is_op(OPERATOR_LSHIFTEQ) | |
3486 | && !token->is_op(OPERATOR_RSHIFTEQ) | |
3487 | && !token->is_op(OPERATOR_ANDEQ) | |
3488 | && !token->is_op(OPERATOR_BITCLEAREQ)) | |
3489 | { | |
3490 | error_at(this->location(), "expected assignment operator"); | |
3491 | return; | |
3492 | } | |
3493 | Operator op = token->op(); | |
3494 | source_location location = token->location(); | |
3495 | ||
3496 | token = this->advance_token(); | |
3497 | ||
3498 | if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE)) | |
3499 | { | |
3500 | if (op != OPERATOR_EQ) | |
3501 | error_at(this->location(), "range clause requires %<=%>"); | |
3502 | this->range_clause_expr(lhs, p_range_clause); | |
3503 | return; | |
3504 | } | |
3505 | ||
3506 | Expression_list* vals = this->expression_list(NULL, false); | |
3507 | ||
3508 | // We've parsed everything; check for errors. | |
3509 | if (lhs == NULL || vals == NULL) | |
3510 | return; | |
3511 | for (Expression_list::const_iterator pe = lhs->begin(); | |
3512 | pe != lhs->end(); | |
3513 | ++pe) | |
3514 | { | |
3515 | if ((*pe)->is_error_expression()) | |
3516 | return; | |
3517 | if (op != OPERATOR_EQ && (*pe)->is_sink_expression()) | |
3518 | error_at((*pe)->location(), "cannot use _ as value"); | |
3519 | } | |
3520 | for (Expression_list::const_iterator pe = vals->begin(); | |
3521 | pe != vals->end(); | |
3522 | ++pe) | |
3523 | { | |
3524 | if ((*pe)->is_error_expression()) | |
3525 | return; | |
3526 | } | |
3527 | ||
3528 | // Map expressions act differently when they are lvalues. | |
3529 | for (Expression_list::iterator plv = lhs->begin(); | |
3530 | plv != lhs->end(); | |
3531 | ++plv) | |
3532 | if ((*plv)->index_expression() != NULL) | |
3533 | (*plv)->index_expression()->set_is_lvalue(); | |
3534 | ||
3535 | Call_expression* call; | |
3536 | Index_expression* map_index; | |
3537 | Receive_expression* receive; | |
3538 | Type_guard_expression* type_guard; | |
3539 | if (lhs->size() == vals->size()) | |
3540 | { | |
3541 | Statement* s; | |
3542 | if (lhs->size() > 1) | |
3543 | { | |
3544 | if (op != OPERATOR_EQ) | |
3545 | error_at(location, "multiple values only permitted with %<=%>"); | |
3546 | s = Statement::make_tuple_assignment(lhs, vals, location); | |
3547 | } | |
3548 | else | |
3549 | { | |
3550 | if (op == OPERATOR_EQ) | |
3551 | s = Statement::make_assignment(lhs->front(), vals->front(), | |
3552 | location); | |
3553 | else | |
3554 | s = Statement::make_assignment_operation(op, lhs->front(), | |
3555 | vals->front(), location); | |
3556 | delete lhs; | |
3557 | delete vals; | |
3558 | } | |
3559 | this->gogo_->add_statement(s); | |
3560 | } | |
3561 | else if (vals->size() == 1 | |
3562 | && (call = (*vals->begin())->call_expression()) != NULL) | |
3563 | { | |
3564 | if (op != OPERATOR_EQ) | |
3565 | error_at(location, "multiple results only permitted with %<=%>"); | |
3566 | delete vals; | |
3567 | vals = new Expression_list; | |
3568 | for (unsigned int i = 0; i < lhs->size(); ++i) | |
3569 | vals->push_back(Expression::make_call_result(call, i)); | |
3570 | Statement* s = Statement::make_tuple_assignment(lhs, vals, location); | |
3571 | this->gogo_->add_statement(s); | |
3572 | } | |
3573 | else if (lhs->size() == 2 | |
3574 | && vals->size() == 1 | |
3575 | && (map_index = (*vals->begin())->index_expression()) != NULL) | |
3576 | { | |
3577 | if (op != OPERATOR_EQ) | |
3578 | error_at(location, "two values from map requires %<=%>"); | |
3579 | Expression* val = lhs->front(); | |
3580 | Expression* present = lhs->back(); | |
3581 | Statement* s = Statement::make_tuple_map_assignment(val, present, | |
3582 | map_index, location); | |
3583 | this->gogo_->add_statement(s); | |
3584 | } | |
3585 | else if (lhs->size() == 1 | |
3586 | && vals->size() == 2 | |
3587 | && (map_index = lhs->front()->index_expression()) != NULL) | |
3588 | { | |
3589 | if (op != OPERATOR_EQ) | |
3590 | error_at(location, "assigning tuple to map index requires %<=%>"); | |
3591 | Expression* val = vals->front(); | |
3592 | Expression* should_set = vals->back(); | |
3593 | Statement* s = Statement::make_map_assignment(map_index, val, should_set, | |
3594 | location); | |
3595 | this->gogo_->add_statement(s); | |
3596 | } | |
3597 | else if (lhs->size() == 2 | |
3598 | && vals->size() == 1 | |
3599 | && (receive = (*vals->begin())->receive_expression()) != NULL) | |
3600 | { | |
3601 | if (op != OPERATOR_EQ) | |
3602 | error_at(location, "two values from receive requires %<=%>"); | |
3603 | Expression* val = lhs->front(); | |
3604 | Expression* success = lhs->back(); | |
3605 | Expression* channel = receive->channel(); | |
3606 | Statement* s = Statement::make_tuple_receive_assignment(val, success, | |
3607 | channel, | |
3608 | location); | |
3609 | this->gogo_->add_statement(s); | |
3610 | } | |
3611 | else if (lhs->size() == 2 | |
3612 | && vals->size() == 1 | |
3613 | && (type_guard = (*vals->begin())->type_guard_expression()) != NULL) | |
3614 | { | |
3615 | if (op != OPERATOR_EQ) | |
3616 | error_at(location, "two values from type guard requires %<=%>"); | |
3617 | Expression* val = lhs->front(); | |
3618 | Expression* ok = lhs->back(); | |
3619 | Expression* expr = type_guard->expr(); | |
3620 | Type* type = type_guard->type(); | |
3621 | Statement* s = Statement::make_tuple_type_guard_assignment(val, ok, | |
3622 | expr, type, | |
3623 | location); | |
3624 | this->gogo_->add_statement(s); | |
3625 | } | |
3626 | else | |
3627 | { | |
3628 | error_at(location, "number of variables does not match number of values"); | |
3629 | } | |
3630 | } | |
3631 | ||
3632 | // GoStat = "go" Expression . | |
3633 | // DeferStat = "defer" Expression . | |
3634 | ||
3635 | void | |
3636 | Parse::go_or_defer_stat() | |
3637 | { | |
3638 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_GO) | |
3639 | || this->peek_token()->is_keyword(KEYWORD_DEFER)); | |
3640 | bool is_go = this->peek_token()->is_keyword(KEYWORD_GO); | |
3641 | source_location stat_location = this->location(); | |
3642 | this->advance_token(); | |
3643 | source_location expr_location = this->location(); | |
3644 | Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
3645 | Call_expression* call_expr = expr->call_expression(); | |
3646 | if (call_expr == NULL) | |
3647 | { | |
3648 | error_at(expr_location, "expected call expression"); | |
3649 | return; | |
3650 | } | |
3651 | ||
3652 | // Make it easier to simplify go/defer statements by putting every | |
3653 | // statement in its own block. | |
3654 | this->gogo_->start_block(stat_location); | |
3655 | Statement* stat; | |
3656 | if (is_go) | |
3657 | stat = Statement::make_go_statement(call_expr, stat_location); | |
3658 | else | |
3659 | stat = Statement::make_defer_statement(call_expr, stat_location); | |
3660 | this->gogo_->add_statement(stat); | |
3661 | this->gogo_->add_block(this->gogo_->finish_block(stat_location), | |
3662 | stat_location); | |
3663 | } | |
3664 | ||
3665 | // ReturnStat = "return" [ ExpressionList ] . | |
3666 | ||
3667 | void | |
3668 | Parse::return_stat() | |
3669 | { | |
3670 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_RETURN)); | |
3671 | source_location location = this->location(); | |
3672 | this->advance_token(); | |
3673 | Expression_list* vals = NULL; | |
3674 | if (this->expression_may_start_here()) | |
3675 | vals = this->expression_list(NULL, false); | |
3676 | const Function* function = this->gogo_->current_function()->func_value(); | |
3677 | const Typed_identifier_list* results = function->type()->results(); | |
3678 | this->gogo_->add_statement(Statement::make_return_statement(results, vals, | |
3679 | location)); | |
3680 | } | |
3681 | ||
3682 | // IfStat = "if" [ [ SimpleStat ] ";" ] [ Condition ] | |
3683 | // Block [ "else" Statement ] . | |
3684 | ||
3685 | void | |
3686 | Parse::if_stat() | |
3687 | { | |
3688 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_IF)); | |
3689 | source_location location = this->location(); | |
3690 | this->advance_token(); | |
3691 | ||
3692 | this->gogo_->start_block(location); | |
3693 | ||
3694 | Expression* cond = NULL; | |
3695 | if (this->simple_stat_may_start_here()) | |
3696 | cond = this->simple_stat(false, true, NULL, NULL); | |
3697 | if (cond != NULL && this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
3698 | { | |
3699 | // The SimpleStat is an expression statement. | |
3700 | this->expression_stat(cond); | |
3701 | cond = NULL; | |
3702 | } | |
3703 | if (cond == NULL) | |
3704 | { | |
3705 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
3706 | this->advance_token(); | |
3707 | if (!this->peek_token()->is_op(OPERATOR_LCURLY)) | |
3708 | cond = this->expression(PRECEDENCE_NORMAL, false, false, NULL); | |
3709 | } | |
3710 | ||
3711 | this->gogo_->start_block(this->location()); | |
3712 | source_location end_loc = this->block(); | |
3713 | Block* then_block = this->gogo_->finish_block(end_loc); | |
3714 | ||
3715 | // Check for the easy error of a newline before "else". | |
3716 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
3717 | { | |
3718 | source_location semi_loc = this->location(); | |
3719 | if (this->advance_token()->is_keyword(KEYWORD_ELSE)) | |
3720 | error_at(this->location(), | |
3721 | "unexpected semicolon or newline before %<else%>"); | |
3722 | else | |
3723 | this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON, | |
3724 | semi_loc)); | |
3725 | } | |
3726 | ||
3727 | Block* else_block = NULL; | |
3728 | if (this->peek_token()->is_keyword(KEYWORD_ELSE)) | |
3729 | { | |
3730 | this->advance_token(); | |
3731 | // We create a block to gather the statement. | |
3732 | this->gogo_->start_block(this->location()); | |
3733 | this->statement(NULL); | |
3734 | else_block = this->gogo_->finish_block(this->location()); | |
3735 | } | |
3736 | ||
3737 | this->gogo_->add_statement(Statement::make_if_statement(cond, then_block, | |
3738 | else_block, | |
3739 | location)); | |
3740 | ||
3741 | this->gogo_->add_block(this->gogo_->finish_block(this->location()), | |
3742 | location); | |
3743 | } | |
3744 | ||
3745 | // SwitchStmt = ExprSwitchStmt | TypeSwitchStmt . | |
3746 | // ExprSwitchStmt = "switch" [ [ SimpleStat ] ";" ] [ Expression ] | |
3747 | // "{" { ExprCaseClause } "}" . | |
3748 | // TypeSwitchStmt = "switch" [ [ SimpleStat ] ";" ] TypeSwitchGuard | |
3749 | // "{" { TypeCaseClause } "}" . | |
3750 | // TypeSwitchGuard = [ identifier ":=" ] Expression "." "(" "type" ")" . | |
3751 | ||
3752 | void | |
3753 | Parse::switch_stat(const Label* label) | |
3754 | { | |
3755 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_SWITCH)); | |
3756 | source_location location = this->location(); | |
3757 | this->advance_token(); | |
3758 | ||
3759 | this->gogo_->start_block(location); | |
3760 | ||
3761 | Expression* switch_val = NULL; | |
3762 | Type_switch type_switch; | |
3763 | if (this->simple_stat_may_start_here()) | |
3764 | switch_val = this->simple_stat(false, true, NULL, &type_switch); | |
3765 | if (switch_val != NULL && this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
3766 | { | |
3767 | // The SimpleStat is an expression statement. | |
3768 | this->expression_stat(switch_val); | |
3769 | switch_val = NULL; | |
3770 | } | |
3771 | if (switch_val == NULL && !type_switch.found) | |
3772 | { | |
3773 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
3774 | this->advance_token(); | |
3775 | if (!this->peek_token()->is_op(OPERATOR_LCURLY)) | |
3776 | { | |
3777 | if (this->peek_token()->is_identifier()) | |
3778 | { | |
3779 | const Token* token = this->peek_token(); | |
3780 | std::string identifier = token->identifier(); | |
3781 | bool is_exported = token->is_identifier_exported(); | |
3782 | source_location id_loc = token->location(); | |
3783 | ||
3784 | token = this->advance_token(); | |
3785 | bool is_coloneq = token->is_op(OPERATOR_COLONEQ); | |
3786 | this->unget_token(Token::make_identifier_token(identifier, | |
3787 | is_exported, | |
3788 | id_loc)); | |
3789 | if (is_coloneq) | |
3790 | { | |
3791 | // This must be a TypeSwitchGuard. | |
3792 | switch_val = this->simple_stat(false, true, NULL, | |
3793 | &type_switch); | |
3794 | if (!type_switch.found | |
3795 | && !switch_val->is_error_expression()) | |
3796 | { | |
3797 | error_at(id_loc, "expected type switch assignment"); | |
3798 | switch_val = Expression::make_error(id_loc); | |
3799 | } | |
3800 | } | |
3801 | } | |
3802 | if (switch_val == NULL && !type_switch.found) | |
3803 | { | |
3804 | switch_val = this->expression(PRECEDENCE_NORMAL, false, false, | |
3805 | &type_switch.found); | |
3806 | if (type_switch.found) | |
3807 | { | |
3808 | type_switch.name.clear(); | |
3809 | type_switch.expr = switch_val; | |
3810 | type_switch.location = switch_val->location(); | |
3811 | } | |
3812 | } | |
3813 | } | |
3814 | } | |
3815 | ||
3816 | if (!this->peek_token()->is_op(OPERATOR_LCURLY)) | |
3817 | { | |
3818 | source_location token_loc = this->location(); | |
3819 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
3820 | && this->advance_token()->is_op(OPERATOR_LCURLY)) | |
3821 | error_at(token_loc, "unexpected semicolon or newline before %<{%>"); | |
3822 | else | |
3823 | { | |
3824 | error_at(this->location(), "expected %<{%>"); | |
3825 | this->gogo_->add_block(this->gogo_->finish_block(this->location()), | |
3826 | location); | |
3827 | return; | |
3828 | } | |
3829 | } | |
3830 | this->advance_token(); | |
3831 | ||
3832 | Statement* statement; | |
3833 | if (type_switch.found) | |
3834 | statement = this->type_switch_body(label, type_switch, location); | |
3835 | else | |
3836 | statement = this->expr_switch_body(label, switch_val, location); | |
3837 | ||
3838 | if (statement != NULL) | |
3839 | this->gogo_->add_statement(statement); | |
3840 | ||
3841 | this->gogo_->add_block(this->gogo_->finish_block(this->location()), | |
3842 | location); | |
3843 | } | |
3844 | ||
3845 | // The body of an expression switch. | |
3846 | // "{" { ExprCaseClause } "}" | |
3847 | ||
3848 | Statement* | |
3849 | Parse::expr_switch_body(const Label* label, Expression* switch_val, | |
3850 | source_location location) | |
3851 | { | |
3852 | Switch_statement* statement = Statement::make_switch_statement(switch_val, | |
3853 | location); | |
3854 | ||
3855 | this->push_break_statement(statement, label); | |
3856 | ||
3857 | Case_clauses* case_clauses = new Case_clauses(); | |
79b4a34a | 3858 | bool saw_default = false; |
7a938933 ILT |
3859 | while (!this->peek_token()->is_op(OPERATOR_RCURLY)) |
3860 | { | |
3861 | if (this->peek_token()->is_eof()) | |
3862 | { | |
3863 | if (!saw_errors()) | |
3864 | error_at(this->location(), "missing %<}%>"); | |
3865 | return NULL; | |
3866 | } | |
79b4a34a | 3867 | this->expr_case_clause(case_clauses, &saw_default); |
7a938933 ILT |
3868 | } |
3869 | this->advance_token(); | |
3870 | ||
3871 | statement->add_clauses(case_clauses); | |
3872 | ||
3873 | this->pop_break_statement(); | |
3874 | ||
3875 | return statement; | |
3876 | } | |
3877 | ||
3878 | // ExprCaseClause = ExprSwitchCase ":" [ StatementList ] . | |
3879 | // FallthroughStat = "fallthrough" . | |
3880 | ||
3881 | void | |
79b4a34a | 3882 | Parse::expr_case_clause(Case_clauses* clauses, bool* saw_default) |
7a938933 ILT |
3883 | { |
3884 | source_location location = this->location(); | |
3885 | ||
3886 | bool is_default = false; | |
3887 | Expression_list* vals = this->expr_switch_case(&is_default); | |
3888 | ||
3889 | if (!this->peek_token()->is_op(OPERATOR_COLON)) | |
3890 | { | |
3891 | if (!saw_errors()) | |
3892 | error_at(this->location(), "expected %<:%>"); | |
3893 | return; | |
3894 | } | |
3895 | else | |
3896 | this->advance_token(); | |
3897 | ||
3898 | Block* statements = NULL; | |
3899 | if (this->statement_list_may_start_here()) | |
3900 | { | |
3901 | this->gogo_->start_block(this->location()); | |
3902 | this->statement_list(); | |
3903 | statements = this->gogo_->finish_block(this->location()); | |
3904 | } | |
3905 | ||
3906 | bool is_fallthrough = false; | |
3907 | if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH)) | |
3908 | { | |
3909 | is_fallthrough = true; | |
3910 | if (this->advance_token()->is_op(OPERATOR_SEMICOLON)) | |
3911 | this->advance_token(); | |
3912 | } | |
3913 | ||
79b4a34a ILT |
3914 | if (is_default) |
3915 | { | |
3916 | if (*saw_default) | |
3917 | { | |
3918 | error_at(location, "multiple defaults in switch"); | |
3919 | return; | |
3920 | } | |
3921 | *saw_default = true; | |
3922 | } | |
3923 | ||
7a938933 ILT |
3924 | if (is_default || vals != NULL) |
3925 | clauses->add(vals, is_default, statements, is_fallthrough, location); | |
3926 | } | |
3927 | ||
3928 | // ExprSwitchCase = "case" ExpressionList | "default" . | |
3929 | ||
3930 | Expression_list* | |
3931 | Parse::expr_switch_case(bool* is_default) | |
3932 | { | |
3933 | const Token* token = this->peek_token(); | |
3934 | if (token->is_keyword(KEYWORD_CASE)) | |
3935 | { | |
3936 | this->advance_token(); | |
3937 | return this->expression_list(NULL, false); | |
3938 | } | |
3939 | else if (token->is_keyword(KEYWORD_DEFAULT)) | |
3940 | { | |
3941 | this->advance_token(); | |
3942 | *is_default = true; | |
3943 | return NULL; | |
3944 | } | |
3945 | else | |
3946 | { | |
3947 | if (!saw_errors()) | |
3948 | error_at(this->location(), "expected %<case%> or %<default%>"); | |
3949 | if (!token->is_op(OPERATOR_RCURLY)) | |
3950 | this->advance_token(); | |
3951 | return NULL; | |
3952 | } | |
3953 | } | |
3954 | ||
3955 | // The body of a type switch. | |
3956 | // "{" { TypeCaseClause } "}" . | |
3957 | ||
3958 | Statement* | |
3959 | Parse::type_switch_body(const Label* label, const Type_switch& type_switch, | |
3960 | source_location location) | |
3961 | { | |
3962 | Named_object* switch_no = NULL; | |
3963 | if (!type_switch.name.empty()) | |
3964 | { | |
3965 | Variable* switch_var = new Variable(NULL, type_switch.expr, false, false, | |
3966 | false, type_switch.location); | |
3967 | switch_no = this->gogo_->add_variable(type_switch.name, switch_var); | |
3968 | } | |
3969 | ||
3970 | Type_switch_statement* statement = | |
3971 | Statement::make_type_switch_statement(switch_no, | |
3972 | (switch_no == NULL | |
3973 | ? type_switch.expr | |
3974 | : NULL), | |
3975 | location); | |
3976 | ||
3977 | this->push_break_statement(statement, label); | |
3978 | ||
3979 | Type_case_clauses* case_clauses = new Type_case_clauses(); | |
79b4a34a | 3980 | bool saw_default = false; |
7a938933 ILT |
3981 | while (!this->peek_token()->is_op(OPERATOR_RCURLY)) |
3982 | { | |
3983 | if (this->peek_token()->is_eof()) | |
3984 | { | |
3985 | error_at(this->location(), "missing %<}%>"); | |
3986 | return NULL; | |
3987 | } | |
79b4a34a | 3988 | this->type_case_clause(switch_no, case_clauses, &saw_default); |
7a938933 ILT |
3989 | } |
3990 | this->advance_token(); | |
3991 | ||
3992 | statement->add_clauses(case_clauses); | |
3993 | ||
3994 | this->pop_break_statement(); | |
3995 | ||
3996 | return statement; | |
3997 | } | |
3998 | ||
3999 | // TypeCaseClause = TypeSwitchCase ":" [ StatementList ] . | |
4000 | ||
4001 | void | |
79b4a34a ILT |
4002 | Parse::type_case_clause(Named_object* switch_no, Type_case_clauses* clauses, |
4003 | bool* saw_default) | |
7a938933 ILT |
4004 | { |
4005 | source_location location = this->location(); | |
4006 | ||
4007 | std::vector<Type*> types; | |
4008 | bool is_default = false; | |
4009 | this->type_switch_case(&types, &is_default); | |
4010 | ||
4011 | if (!this->peek_token()->is_op(OPERATOR_COLON)) | |
4012 | error_at(this->location(), "expected %<:%>"); | |
4013 | else | |
4014 | this->advance_token(); | |
4015 | ||
4016 | Block* statements = NULL; | |
4017 | if (this->statement_list_may_start_here()) | |
4018 | { | |
4019 | this->gogo_->start_block(this->location()); | |
4020 | if (switch_no != NULL && types.size() == 1) | |
4021 | { | |
4022 | Type* type = types.front(); | |
4023 | Expression* init = Expression::make_var_reference(switch_no, | |
4024 | location); | |
4025 | init = Expression::make_type_guard(init, type, location); | |
4026 | Variable* v = new Variable(type, init, false, false, false, | |
4027 | location); | |
4028 | v->set_is_type_switch_var(); | |
4029 | this->gogo_->add_variable(switch_no->name(), v); | |
4030 | } | |
4031 | this->statement_list(); | |
4032 | statements = this->gogo_->finish_block(this->location()); | |
4033 | } | |
4034 | ||
4035 | if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH)) | |
4036 | { | |
4037 | error_at(this->location(), | |
4038 | "fallthrough is not permitted in a type switch"); | |
4039 | if (this->advance_token()->is_op(OPERATOR_SEMICOLON)) | |
4040 | this->advance_token(); | |
4041 | } | |
4042 | ||
4043 | if (is_default) | |
4044 | { | |
4045 | gcc_assert(types.empty()); | |
79b4a34a ILT |
4046 | if (*saw_default) |
4047 | { | |
4048 | error_at(location, "multiple defaults in type switch"); | |
4049 | return; | |
4050 | } | |
4051 | *saw_default = true; | |
7a938933 ILT |
4052 | clauses->add(NULL, false, true, statements, location); |
4053 | } | |
4054 | else if (!types.empty()) | |
4055 | { | |
4056 | for (std::vector<Type*>::const_iterator p = types.begin(); | |
4057 | p + 1 != types.end(); | |
4058 | ++p) | |
4059 | clauses->add(*p, true, false, NULL, location); | |
4060 | clauses->add(types.back(), false, false, statements, location); | |
4061 | } | |
3870e7a5 ILT |
4062 | else |
4063 | clauses->add(Type::make_error_type(), false, false, statements, location); | |
7a938933 ILT |
4064 | } |
4065 | ||
4066 | // TypeSwitchCase = "case" type | "default" | |
4067 | ||
4068 | // We accept a comma separated list of types. | |
4069 | ||
4070 | void | |
4071 | Parse::type_switch_case(std::vector<Type*>* types, bool* is_default) | |
4072 | { | |
4073 | const Token* token = this->peek_token(); | |
4074 | if (token->is_keyword(KEYWORD_CASE)) | |
4075 | { | |
4076 | this->advance_token(); | |
4077 | while (true) | |
4078 | { | |
4079 | Type* t = this->type(); | |
4080 | if (!t->is_error_type()) | |
4081 | types->push_back(t); | |
4082 | if (!this->peek_token()->is_op(OPERATOR_COMMA)) | |
4083 | break; | |
4084 | this->advance_token(); | |
4085 | } | |
4086 | } | |
4087 | else if (token->is_keyword(KEYWORD_DEFAULT)) | |
4088 | { | |
4089 | this->advance_token(); | |
4090 | *is_default = true; | |
4091 | } | |
4092 | else | |
4093 | { | |
4094 | error_at(this->location(), "expected %<case%> or %<default%>"); | |
4095 | if (!token->is_op(OPERATOR_RCURLY)) | |
4096 | this->advance_token(); | |
4097 | } | |
4098 | } | |
4099 | ||
4100 | // SelectStat = "select" "{" { CommClause } "}" . | |
4101 | ||
4102 | void | |
4103 | Parse::select_stat(const Label* label) | |
4104 | { | |
4105 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_SELECT)); | |
4106 | source_location location = this->location(); | |
4107 | const Token* token = this->advance_token(); | |
4108 | ||
4109 | if (!token->is_op(OPERATOR_LCURLY)) | |
4110 | { | |
4111 | source_location token_loc = token->location(); | |
4112 | if (token->is_op(OPERATOR_SEMICOLON) | |
4113 | && this->advance_token()->is_op(OPERATOR_LCURLY)) | |
4114 | error_at(token_loc, "unexpected semicolon or newline before %<{%>"); | |
4115 | else | |
4116 | { | |
4117 | error_at(this->location(), "expected %<{%>"); | |
4118 | return; | |
4119 | } | |
4120 | } | |
4121 | this->advance_token(); | |
4122 | ||
4123 | Select_statement* statement = Statement::make_select_statement(location); | |
4124 | ||
4125 | this->push_break_statement(statement, label); | |
4126 | ||
4127 | Select_clauses* select_clauses = new Select_clauses(); | |
79b4a34a | 4128 | bool saw_default = false; |
7a938933 ILT |
4129 | while (!this->peek_token()->is_op(OPERATOR_RCURLY)) |
4130 | { | |
4131 | if (this->peek_token()->is_eof()) | |
4132 | { | |
4133 | error_at(this->location(), "expected %<}%>"); | |
4134 | return; | |
4135 | } | |
79b4a34a | 4136 | this->comm_clause(select_clauses, &saw_default); |
7a938933 ILT |
4137 | } |
4138 | ||
4139 | this->advance_token(); | |
4140 | ||
4141 | statement->add_clauses(select_clauses); | |
4142 | ||
4143 | this->pop_break_statement(); | |
4144 | ||
4145 | this->gogo_->add_statement(statement); | |
4146 | } | |
4147 | ||
4148 | // CommClause = CommCase [ StatementList ] . | |
4149 | ||
4150 | void | |
79b4a34a | 4151 | Parse::comm_clause(Select_clauses* clauses, bool* saw_default) |
7a938933 ILT |
4152 | { |
4153 | source_location location = this->location(); | |
4154 | bool is_send = false; | |
4155 | Expression* channel = NULL; | |
4156 | Expression* val = NULL; | |
4157 | std::string varname; | |
4158 | bool is_default = false; | |
4159 | bool got_case = this->comm_case(&is_send, &channel, &val, &varname, | |
4160 | &is_default); | |
4161 | ||
4162 | Block* statements = NULL; | |
4163 | Named_object* var = NULL; | |
4164 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
4165 | this->advance_token(); | |
4166 | else if (this->statement_list_may_start_here()) | |
4167 | { | |
4168 | this->gogo_->start_block(this->location()); | |
4169 | ||
4170 | if (!varname.empty()) | |
4171 | { | |
4172 | // FIXME: LOCATION is slightly wrong here. | |
4173 | Variable* v = new Variable(NULL, channel, false, false, false, | |
4174 | location); | |
4175 | v->set_type_from_chan_element(); | |
4176 | var = this->gogo_->add_variable(varname, v); | |
4177 | } | |
4178 | ||
4179 | this->statement_list(); | |
4180 | statements = this->gogo_->finish_block(this->location()); | |
4181 | } | |
4182 | ||
79b4a34a ILT |
4183 | if (is_default) |
4184 | { | |
4185 | if (*saw_default) | |
4186 | { | |
4187 | error_at(location, "multiple defaults in select"); | |
4188 | return; | |
4189 | } | |
4190 | *saw_default = true; | |
4191 | } | |
4192 | ||
7a938933 ILT |
4193 | if (got_case) |
4194 | clauses->add(is_send, channel, val, var, is_default, statements, location); | |
4195 | } | |
4196 | ||
4197 | // CommCase = ( "default" | ( "case" ( SendExpr | RecvExpr) ) ) ":" . | |
4198 | ||
4199 | bool | |
4200 | Parse::comm_case(bool* is_send, Expression** channel, Expression** val, | |
4201 | std::string* varname, bool* is_default) | |
4202 | { | |
4203 | const Token* token = this->peek_token(); | |
4204 | if (token->is_keyword(KEYWORD_DEFAULT)) | |
4205 | { | |
4206 | this->advance_token(); | |
4207 | *is_default = true; | |
4208 | } | |
4209 | else if (token->is_keyword(KEYWORD_CASE)) | |
4210 | { | |
4211 | this->advance_token(); | |
4212 | if (!this->send_or_recv_expr(is_send, channel, val, varname)) | |
4213 | return false; | |
4214 | } | |
4215 | else | |
4216 | { | |
4217 | error_at(this->location(), "expected %<case%> or %<default%>"); | |
4218 | if (!token->is_op(OPERATOR_RCURLY)) | |
4219 | this->advance_token(); | |
4220 | return false; | |
4221 | } | |
4222 | ||
4223 | if (!this->peek_token()->is_op(OPERATOR_COLON)) | |
4224 | { | |
4225 | error_at(this->location(), "expected colon"); | |
4226 | return false; | |
4227 | } | |
4228 | ||
4229 | this->advance_token(); | |
4230 | ||
4231 | return true; | |
4232 | } | |
4233 | ||
4234 | // SendExpr = Expression "<-" Expression . | |
4235 | // RecvExpr = [ Expression ( "=" | ":=" ) ] "<-" Expression . | |
4236 | ||
4237 | bool | |
4238 | Parse::send_or_recv_expr(bool* is_send, Expression** channel, Expression** val, | |
4239 | std::string* varname) | |
4240 | { | |
4241 | const Token* token = this->peek_token(); | |
4242 | source_location location = token->location(); | |
4243 | if (token->is_identifier()) | |
4244 | { | |
4245 | std::string recv_var = token->identifier(); | |
4246 | bool is_var_exported = token->is_identifier_exported(); | |
4247 | if (!this->advance_token()->is_op(OPERATOR_COLONEQ)) | |
4248 | this->unget_token(Token::make_identifier_token(recv_var, | |
4249 | is_var_exported, | |
4250 | location)); | |
4251 | else | |
4252 | { | |
4253 | if (!this->advance_token()->is_op(OPERATOR_CHANOP)) | |
4254 | { | |
4255 | error_at(this->location(), "expected %<<-%>"); | |
4256 | return false; | |
4257 | } | |
4258 | *is_send = false; | |
4259 | *varname = this->gogo_->pack_hidden_name(recv_var, is_var_exported); | |
4260 | this->advance_token(); | |
4261 | *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
4262 | return true; | |
4263 | } | |
4264 | } | |
4265 | ||
4266 | if (this->peek_token()->is_op(OPERATOR_CHANOP)) | |
4267 | { | |
4268 | *is_send = false; | |
4269 | this->advance_token(); | |
4270 | *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
4271 | } | |
4272 | else | |
4273 | { | |
4274 | Expression* left = this->expression(PRECEDENCE_CHANOP, true, true, NULL); | |
4275 | ||
4276 | if (this->peek_token()->is_op(OPERATOR_EQ)) | |
4277 | { | |
4278 | if (!this->advance_token()->is_op(OPERATOR_CHANOP)) | |
4279 | { | |
4280 | error_at(this->location(), "missing %<<-%>"); | |
4281 | return false; | |
4282 | } | |
4283 | *is_send = false; | |
4284 | *val = left; | |
4285 | this->advance_token(); | |
4286 | *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
4287 | } | |
4288 | else if (this->peek_token()->is_op(OPERATOR_CHANOP)) | |
4289 | { | |
4290 | *is_send = true; | |
4291 | *channel = this->verify_not_sink(left); | |
4292 | this->advance_token(); | |
4293 | *val = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
4294 | } | |
4295 | else | |
4296 | { | |
4297 | error_at(this->location(), "expected %<<-%> or %<=%>"); | |
4298 | return false; | |
4299 | } | |
4300 | } | |
4301 | ||
4302 | return true; | |
4303 | } | |
4304 | ||
4305 | // ForStat = "for" [ Condition | ForClause | RangeClause ] Block . | |
4306 | // Condition = Expression . | |
4307 | ||
4308 | void | |
4309 | Parse::for_stat(const Label* label) | |
4310 | { | |
4311 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_FOR)); | |
4312 | source_location location = this->location(); | |
4313 | const Token* token = this->advance_token(); | |
4314 | ||
4315 | // Open a block to hold any variables defined in the init statement | |
4316 | // of the for statement. | |
4317 | this->gogo_->start_block(location); | |
4318 | ||
4319 | Block* init = NULL; | |
4320 | Expression* cond = NULL; | |
4321 | Block* post = NULL; | |
4322 | Range_clause range_clause; | |
4323 | ||
4324 | if (!token->is_op(OPERATOR_LCURLY)) | |
4325 | { | |
4326 | if (token->is_keyword(KEYWORD_VAR)) | |
4327 | { | |
4328 | error_at(this->location(), | |
4329 | "var declaration not allowed in for initializer"); | |
4330 | this->var_decl(); | |
4331 | } | |
4332 | ||
4333 | if (token->is_op(OPERATOR_SEMICOLON)) | |
4334 | this->for_clause(&cond, &post); | |
4335 | else | |
4336 | { | |
4337 | // We might be looking at a Condition, an InitStat, or a | |
4338 | // RangeClause. | |
4339 | cond = this->simple_stat(false, true, &range_clause, NULL); | |
4340 | if (!this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
4341 | { | |
4342 | if (cond == NULL && !range_clause.found) | |
4343 | error_at(this->location(), "parse error in for statement"); | |
4344 | } | |
4345 | else | |
4346 | { | |
4347 | if (range_clause.found) | |
4348 | error_at(this->location(), "parse error after range clause"); | |
4349 | ||
4350 | if (cond != NULL) | |
4351 | { | |
4352 | // COND is actually an expression statement for | |
4353 | // InitStat at the start of a ForClause. | |
4354 | this->expression_stat(cond); | |
4355 | cond = NULL; | |
4356 | } | |
4357 | ||
4358 | this->for_clause(&cond, &post); | |
4359 | } | |
4360 | } | |
4361 | } | |
4362 | ||
4363 | // Build the For_statement and note that it is the current target | |
4364 | // for break and continue statements. | |
4365 | ||
4366 | For_statement* sfor; | |
4367 | For_range_statement* srange; | |
4368 | Statement* s; | |
4369 | if (!range_clause.found) | |
4370 | { | |
4371 | sfor = Statement::make_for_statement(init, cond, post, location); | |
4372 | s = sfor; | |
4373 | srange = NULL; | |
4374 | } | |
4375 | else | |
4376 | { | |
4377 | srange = Statement::make_for_range_statement(range_clause.index, | |
4378 | range_clause.value, | |
4379 | range_clause.range, | |
4380 | location); | |
4381 | s = srange; | |
4382 | sfor = NULL; | |
4383 | } | |
4384 | ||
4385 | this->push_break_statement(s, label); | |
4386 | this->push_continue_statement(s, label); | |
4387 | ||
4388 | // Gather the block of statements in the loop and add them to the | |
4389 | // For_statement. | |
4390 | ||
4391 | this->gogo_->start_block(this->location()); | |
4392 | source_location end_loc = this->block(); | |
4393 | Block* statements = this->gogo_->finish_block(end_loc); | |
4394 | ||
4395 | if (sfor != NULL) | |
4396 | sfor->add_statements(statements); | |
4397 | else | |
4398 | srange->add_statements(statements); | |
4399 | ||
4400 | // This is no longer the break/continue target. | |
4401 | this->pop_break_statement(); | |
4402 | this->pop_continue_statement(); | |
4403 | ||
4404 | // Add the For_statement to the list of statements, and close out | |
4405 | // the block we started to hold any variables defined in the for | |
4406 | // statement. | |
4407 | ||
4408 | this->gogo_->add_statement(s); | |
4409 | ||
4410 | this->gogo_->add_block(this->gogo_->finish_block(this->location()), | |
4411 | location); | |
4412 | } | |
4413 | ||
4414 | // ForClause = [ InitStat ] ";" [ Condition ] ";" [ PostStat ] . | |
4415 | // InitStat = SimpleStat . | |
4416 | // PostStat = SimpleStat . | |
4417 | ||
4418 | // We have already read InitStat at this point. | |
4419 | ||
4420 | void | |
4421 | Parse::for_clause(Expression** cond, Block** post) | |
4422 | { | |
4423 | gcc_assert(this->peek_token()->is_op(OPERATOR_SEMICOLON)); | |
4424 | this->advance_token(); | |
4425 | if (this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
4426 | *cond = NULL; | |
4427 | else if (this->peek_token()->is_op(OPERATOR_LCURLY)) | |
4428 | { | |
4429 | error_at(this->location(), | |
4430 | "unexpected semicolon or newline before %<{%>"); | |
4431 | *cond = NULL; | |
4432 | *post = NULL; | |
4433 | return; | |
4434 | } | |
4435 | else | |
4436 | *cond = this->expression(PRECEDENCE_NORMAL, false, true, NULL); | |
4437 | if (!this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
4438 | error_at(this->location(), "expected semicolon"); | |
4439 | else | |
4440 | this->advance_token(); | |
4441 | ||
4442 | if (this->peek_token()->is_op(OPERATOR_LCURLY)) | |
4443 | *post = NULL; | |
4444 | else | |
4445 | { | |
4446 | this->gogo_->start_block(this->location()); | |
4447 | this->simple_stat(false, false, NULL, NULL); | |
4448 | *post = this->gogo_->finish_block(this->location()); | |
4449 | } | |
4450 | } | |
4451 | ||
4452 | // RangeClause = IdentifierList ( "=" | ":=" ) "range" Expression . | |
4453 | ||
4454 | // This is the := version. It is called with a list of identifiers. | |
4455 | ||
4456 | void | |
4457 | Parse::range_clause_decl(const Typed_identifier_list* til, | |
4458 | Range_clause* p_range_clause) | |
4459 | { | |
4460 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_RANGE)); | |
4461 | source_location location = this->location(); | |
4462 | ||
4463 | p_range_clause->found = true; | |
4464 | ||
4465 | gcc_assert(til->size() >= 1); | |
4466 | if (til->size() > 2) | |
4467 | error_at(this->location(), "too many variables for range clause"); | |
4468 | ||
4469 | this->advance_token(); | |
4470 | Expression* expr = this->expression(PRECEDENCE_NORMAL, false, false, NULL); | |
4471 | p_range_clause->range = expr; | |
4472 | ||
4473 | bool any_new = false; | |
4474 | ||
4475 | const Typed_identifier* pti = &til->front(); | |
4476 | Named_object* no = this->init_var(*pti, NULL, expr, true, true, &any_new); | |
4477 | if (any_new && no->is_variable()) | |
4478 | no->var_value()->set_type_from_range_index(); | |
4479 | p_range_clause->index = Expression::make_var_reference(no, location); | |
4480 | ||
4481 | if (til->size() == 1) | |
4482 | p_range_clause->value = NULL; | |
4483 | else | |
4484 | { | |
4485 | pti = &til->back(); | |
4486 | bool is_new = false; | |
4487 | no = this->init_var(*pti, NULL, expr, true, true, &is_new); | |
4488 | if (is_new && no->is_variable()) | |
4489 | no->var_value()->set_type_from_range_value(); | |
4490 | if (is_new) | |
4491 | any_new = true; | |
4492 | p_range_clause->value = Expression::make_var_reference(no, location); | |
4493 | } | |
4494 | ||
4495 | if (!any_new) | |
4496 | error_at(location, "variables redeclared but no variable is new"); | |
4497 | } | |
4498 | ||
4499 | // The = version of RangeClause. This is called with a list of | |
4500 | // expressions. | |
4501 | ||
4502 | void | |
4503 | Parse::range_clause_expr(const Expression_list* vals, | |
4504 | Range_clause* p_range_clause) | |
4505 | { | |
4506 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_RANGE)); | |
4507 | ||
4508 | p_range_clause->found = true; | |
4509 | ||
4510 | gcc_assert(vals->size() >= 1); | |
4511 | if (vals->size() > 2) | |
4512 | error_at(this->location(), "too many variables for range clause"); | |
4513 | ||
4514 | this->advance_token(); | |
4515 | p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false, | |
4516 | NULL); | |
4517 | ||
4518 | p_range_clause->index = vals->front(); | |
4519 | if (vals->size() == 1) | |
4520 | p_range_clause->value = NULL; | |
4521 | else | |
4522 | p_range_clause->value = vals->back(); | |
4523 | } | |
4524 | ||
4525 | // Push a statement on the break stack. | |
4526 | ||
4527 | void | |
4528 | Parse::push_break_statement(Statement* enclosing, const Label* label) | |
4529 | { | |
bdc4349d ILT |
4530 | if (this->break_stack_ == NULL) |
4531 | this->break_stack_ = new Bc_stack(); | |
4532 | this->break_stack_->push_back(std::make_pair(enclosing, label)); | |
7a938933 ILT |
4533 | } |
4534 | ||
4535 | // Push a statement on the continue stack. | |
4536 | ||
4537 | void | |
4538 | Parse::push_continue_statement(Statement* enclosing, const Label* label) | |
4539 | { | |
bdc4349d ILT |
4540 | if (this->continue_stack_ == NULL) |
4541 | this->continue_stack_ = new Bc_stack(); | |
4542 | this->continue_stack_->push_back(std::make_pair(enclosing, label)); | |
7a938933 ILT |
4543 | } |
4544 | ||
4545 | // Pop the break stack. | |
4546 | ||
4547 | void | |
4548 | Parse::pop_break_statement() | |
4549 | { | |
bdc4349d | 4550 | this->break_stack_->pop_back(); |
7a938933 ILT |
4551 | } |
4552 | ||
4553 | // Pop the continue stack. | |
4554 | ||
4555 | void | |
4556 | Parse::pop_continue_statement() | |
4557 | { | |
bdc4349d | 4558 | this->continue_stack_->pop_back(); |
7a938933 ILT |
4559 | } |
4560 | ||
4561 | // Find a break or continue statement given a label name. | |
4562 | ||
4563 | Statement* | |
4564 | Parse::find_bc_statement(const Bc_stack* bc_stack, const std::string& label) | |
4565 | { | |
bdc4349d ILT |
4566 | if (bc_stack == NULL) |
4567 | return NULL; | |
7a938933 ILT |
4568 | for (Bc_stack::const_reverse_iterator p = bc_stack->rbegin(); |
4569 | p != bc_stack->rend(); | |
4570 | ++p) | |
4571 | if (p->second != NULL && p->second->name() == label) | |
4572 | return p->first; | |
4573 | return NULL; | |
4574 | } | |
4575 | ||
4576 | // BreakStat = "break" [ identifier ] . | |
4577 | ||
4578 | void | |
4579 | Parse::break_stat() | |
4580 | { | |
4581 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_BREAK)); | |
4582 | source_location location = this->location(); | |
4583 | ||
4584 | const Token* token = this->advance_token(); | |
4585 | Statement* enclosing; | |
4586 | if (!token->is_identifier()) | |
4587 | { | |
bdc4349d | 4588 | if (this->break_stack_ == NULL || this->break_stack_->empty()) |
7a938933 ILT |
4589 | { |
4590 | error_at(this->location(), | |
4591 | "break statement not within for or switch or select"); | |
4592 | return; | |
4593 | } | |
bdc4349d | 4594 | enclosing = this->break_stack_->back().first; |
7a938933 ILT |
4595 | } |
4596 | else | |
4597 | { | |
bdc4349d | 4598 | enclosing = this->find_bc_statement(this->break_stack_, |
7a938933 ILT |
4599 | token->identifier()); |
4600 | if (enclosing == NULL) | |
4601 | { | |
4602 | error_at(token->location(), | |
4603 | ("break label %qs not associated with " | |
4604 | "for or switch or select"), | |
4605 | Gogo::message_name(token->identifier()).c_str()); | |
4606 | this->advance_token(); | |
4607 | return; | |
4608 | } | |
4609 | this->advance_token(); | |
4610 | } | |
4611 | ||
4612 | Unnamed_label* label; | |
4613 | if (enclosing->classification() == Statement::STATEMENT_FOR) | |
4614 | label = enclosing->for_statement()->break_label(); | |
4615 | else if (enclosing->classification() == Statement::STATEMENT_FOR_RANGE) | |
4616 | label = enclosing->for_range_statement()->break_label(); | |
4617 | else if (enclosing->classification() == Statement::STATEMENT_SWITCH) | |
4618 | label = enclosing->switch_statement()->break_label(); | |
4619 | else if (enclosing->classification() == Statement::STATEMENT_TYPE_SWITCH) | |
4620 | label = enclosing->type_switch_statement()->break_label(); | |
4621 | else if (enclosing->classification() == Statement::STATEMENT_SELECT) | |
4622 | label = enclosing->select_statement()->break_label(); | |
4623 | else | |
4624 | gcc_unreachable(); | |
4625 | ||
4626 | this->gogo_->add_statement(Statement::make_break_statement(label, | |
4627 | location)); | |
4628 | } | |
4629 | ||
4630 | // ContinueStat = "continue" [ identifier ] . | |
4631 | ||
4632 | void | |
4633 | Parse::continue_stat() | |
4634 | { | |
4635 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_CONTINUE)); | |
4636 | source_location location = this->location(); | |
4637 | ||
4638 | const Token* token = this->advance_token(); | |
4639 | Statement* enclosing; | |
4640 | if (!token->is_identifier()) | |
4641 | { | |
bdc4349d | 4642 | if (this->continue_stack_ == NULL || this->continue_stack_->empty()) |
7a938933 ILT |
4643 | { |
4644 | error_at(this->location(), "continue statement not within for"); | |
4645 | return; | |
4646 | } | |
bdc4349d | 4647 | enclosing = this->continue_stack_->back().first; |
7a938933 ILT |
4648 | } |
4649 | else | |
4650 | { | |
bdc4349d | 4651 | enclosing = this->find_bc_statement(this->continue_stack_, |
7a938933 ILT |
4652 | token->identifier()); |
4653 | if (enclosing == NULL) | |
4654 | { | |
4655 | error_at(token->location(), | |
4656 | "continue label %qs not associated with for", | |
4657 | Gogo::message_name(token->identifier()).c_str()); | |
4658 | this->advance_token(); | |
4659 | return; | |
4660 | } | |
4661 | this->advance_token(); | |
4662 | } | |
4663 | ||
4664 | Unnamed_label* label; | |
4665 | if (enclosing->classification() == Statement::STATEMENT_FOR) | |
4666 | label = enclosing->for_statement()->continue_label(); | |
4667 | else if (enclosing->classification() == Statement::STATEMENT_FOR_RANGE) | |
4668 | label = enclosing->for_range_statement()->continue_label(); | |
4669 | else | |
4670 | gcc_unreachable(); | |
4671 | ||
4672 | this->gogo_->add_statement(Statement::make_continue_statement(label, | |
4673 | location)); | |
4674 | } | |
4675 | ||
4676 | // GotoStat = "goto" identifier . | |
4677 | ||
4678 | void | |
4679 | Parse::goto_stat() | |
4680 | { | |
4681 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_GOTO)); | |
4682 | source_location location = this->location(); | |
4683 | const Token* token = this->advance_token(); | |
4684 | if (!token->is_identifier()) | |
4685 | error_at(this->location(), "expected label for goto"); | |
4686 | else | |
4687 | { | |
4688 | Label* label = this->gogo_->add_label_reference(token->identifier()); | |
4689 | Statement* s = Statement::make_goto_statement(label, location); | |
4690 | this->gogo_->add_statement(s); | |
4691 | this->advance_token(); | |
4692 | } | |
4693 | } | |
4694 | ||
4695 | // PackageClause = "package" PackageName . | |
4696 | ||
4697 | void | |
4698 | Parse::package_clause() | |
4699 | { | |
4700 | const Token* token = this->peek_token(); | |
4701 | source_location location = token->location(); | |
4702 | std::string name; | |
4703 | if (!token->is_keyword(KEYWORD_PACKAGE)) | |
4704 | { | |
4705 | error_at(this->location(), "program must start with package clause"); | |
4706 | name = "ERROR"; | |
4707 | } | |
4708 | else | |
4709 | { | |
4710 | token = this->advance_token(); | |
4711 | if (token->is_identifier()) | |
4712 | { | |
4713 | name = token->identifier(); | |
4714 | if (name == "_") | |
4715 | { | |
4716 | error_at(this->location(), "invalid package name _"); | |
4717 | name = "blank"; | |
4718 | } | |
4719 | this->advance_token(); | |
4720 | } | |
4721 | else | |
4722 | { | |
4723 | error_at(this->location(), "package name must be an identifier"); | |
4724 | name = "ERROR"; | |
4725 | } | |
4726 | } | |
4727 | this->gogo_->set_package_name(name, location); | |
4728 | } | |
4729 | ||
4730 | // ImportDecl = "import" Decl<ImportSpec> . | |
4731 | ||
4732 | void | |
4733 | Parse::import_decl() | |
4734 | { | |
4735 | gcc_assert(this->peek_token()->is_keyword(KEYWORD_IMPORT)); | |
4736 | this->advance_token(); | |
4737 | this->decl(&Parse::import_spec, NULL); | |
4738 | } | |
4739 | ||
4740 | // ImportSpec = [ "." | PackageName ] PackageFileName . | |
4741 | ||
4742 | void | |
4743 | Parse::import_spec(void*) | |
4744 | { | |
4745 | const Token* token = this->peek_token(); | |
4746 | source_location location = token->location(); | |
4747 | ||
4748 | std::string local_name; | |
4749 | bool is_local_name_exported = false; | |
4750 | if (token->is_op(OPERATOR_DOT)) | |
4751 | { | |
4752 | local_name = "."; | |
4753 | token = this->advance_token(); | |
4754 | } | |
4755 | else if (token->is_identifier()) | |
4756 | { | |
4757 | local_name = token->identifier(); | |
4758 | is_local_name_exported = token->is_identifier_exported(); | |
4759 | token = this->advance_token(); | |
4760 | } | |
4761 | ||
4762 | if (!token->is_string()) | |
4763 | { | |
4764 | error_at(this->location(), "missing import package name"); | |
4765 | return; | |
4766 | } | |
4767 | ||
4768 | this->gogo_->import_package(token->string_value(), local_name, | |
4769 | is_local_name_exported, location); | |
4770 | ||
4771 | this->advance_token(); | |
4772 | } | |
4773 | ||
4774 | // SourceFile = PackageClause ";" { ImportDecl ";" } | |
4775 | // { TopLevelDecl ";" } . | |
4776 | ||
4777 | void | |
4778 | Parse::program() | |
4779 | { | |
4780 | this->package_clause(); | |
4781 | ||
4782 | const Token* token = this->peek_token(); | |
4783 | if (token->is_op(OPERATOR_SEMICOLON)) | |
4784 | token = this->advance_token(); | |
4785 | else | |
4786 | error_at(this->location(), | |
4787 | "expected %<;%> or newline after package clause"); | |
4788 | ||
4789 | while (token->is_keyword(KEYWORD_IMPORT)) | |
4790 | { | |
4791 | this->import_decl(); | |
4792 | token = this->peek_token(); | |
4793 | if (token->is_op(OPERATOR_SEMICOLON)) | |
4794 | token = this->advance_token(); | |
4795 | else | |
4796 | error_at(this->location(), | |
4797 | "expected %<;%> or newline after import declaration"); | |
4798 | } | |
4799 | ||
4800 | while (!token->is_eof()) | |
4801 | { | |
4802 | if (this->declaration_may_start_here()) | |
4803 | this->declaration(); | |
4804 | else | |
4805 | { | |
4806 | error_at(this->location(), "expected declaration"); | |
4807 | do | |
4808 | this->advance_token(); | |
4809 | while (!this->peek_token()->is_eof() | |
4810 | && !this->peek_token()->is_op(OPERATOR_SEMICOLON) | |
4811 | && !this->peek_token()->is_op(OPERATOR_RCURLY)); | |
4812 | if (!this->peek_token()->is_eof() | |
4813 | && !this->peek_token()->is_op(OPERATOR_SEMICOLON)) | |
4814 | this->advance_token(); | |
4815 | } | |
4816 | token = this->peek_token(); | |
4817 | if (token->is_op(OPERATOR_SEMICOLON)) | |
4818 | token = this->advance_token(); | |
4819 | else if (!token->is_eof() || !saw_errors()) | |
4820 | { | |
4821 | error_at(this->location(), | |
4822 | "expected %<;%> or newline after top level declaration"); | |
4823 | this->skip_past_error(OPERATOR_INVALID); | |
4824 | } | |
4825 | } | |
4826 | } | |
4827 | ||
4828 | // Reset the current iota value. | |
4829 | ||
4830 | void | |
4831 | Parse::reset_iota() | |
4832 | { | |
4833 | this->iota_ = 0; | |
4834 | } | |
4835 | ||
4836 | // Return the current iota value. | |
4837 | ||
4838 | int | |
4839 | Parse::iota_value() | |
4840 | { | |
4841 | return this->iota_; | |
4842 | } | |
4843 | ||
4844 | // Increment the current iota value. | |
4845 | ||
4846 | void | |
4847 | Parse::increment_iota() | |
4848 | { | |
4849 | ++this->iota_; | |
4850 | } | |
4851 | ||
4852 | // Skip forward to a semicolon or OP. OP will normally be | |
4853 | // OPERATOR_RPAREN or OPERATOR_RCURLY. If we find a semicolon, move | |
4854 | // past it and return. If we find OP, it will be the next token to | |
4855 | // read. Return true if we are OK, false if we found EOF. | |
4856 | ||
4857 | bool | |
4858 | Parse::skip_past_error(Operator op) | |
4859 | { | |
4860 | const Token* token = this->peek_token(); | |
4861 | while (!token->is_op(op)) | |
4862 | { | |
4863 | if (token->is_eof()) | |
4864 | return false; | |
4865 | if (token->is_op(OPERATOR_SEMICOLON)) | |
4866 | { | |
4867 | this->advance_token(); | |
4868 | return true; | |
4869 | } | |
4870 | token = this->advance_token(); | |
4871 | } | |
4872 | return true; | |
4873 | } | |
4874 | ||
4875 | // Check that an expression is not a sink. | |
4876 | ||
4877 | Expression* | |
4878 | Parse::verify_not_sink(Expression* expr) | |
4879 | { | |
4880 | if (expr->is_sink_expression()) | |
4881 | { | |
4882 | error_at(expr->location(), "cannot use _ as value"); | |
4883 | expr = Expression::make_error(expr->location()); | |
4884 | } | |
4885 | return expr; | |
4886 | } |