Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(934)

Unified Diff: runtime/vm/parser.cc

Issue 18801007: Support type parameters and classes as expression in the vm. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-dart2dart.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 24832)
+++ runtime/vm/parser.cc (working copy)
@@ -2643,8 +2643,7 @@
// We have a library prefix qualified identifier, unless the prefix is
// shadowed by a type parameter in scope.
if (current_class().IsNull() ||
- (current_class().LookupTypeParameter(*(qual_ident->ident),
- TokenPos()) ==
+ (current_class().LookupTypeParameter(*(qual_ident->ident)) ==
TypeParameter::null())) {
ConsumeToken(); // Consume the kPERIOD token.
qual_ident->lib_prefix = &lib_prefix;
@@ -5913,12 +5912,9 @@
AstNode* loop_var_primary =
ResolveIdent(loop_var_pos, *loop_var_name, false);
ASSERT(!loop_var_primary->IsPrimaryNode());
- loop_var_assignment =
- CreateAssignmentNode(loop_var_primary, iterator_current);
- if (loop_var_assignment == NULL) {
- ErrorMsg(loop_var_pos, "variable or field '%s' is not assignable",
- loop_var_name->ToCString());
- }
+ loop_var_assignment = CreateAssignmentNode(
+ loop_var_primary, iterator_current, loop_var_name, loop_var_pos);
+ ASSERT(loop_var_assignment != NULL);
}
current_block_->statements->Add(loop_var_assignment);
@@ -7010,17 +7006,6 @@
}
-bool Parser::IsAssignableExpr(AstNode* expr) {
- return (expr->IsLoadLocalNode()
- && (!expr->AsLoadLocalNode()->local().is_final()))
- || expr->IsLoadStaticFieldNode()
- || expr->IsStaticGetterNode()
- || expr->IsInstanceGetterNode()
- || expr->IsLoadIndexedNode()
- || (expr->IsPrimaryNode() && !expr->AsPrimaryNode()->IsSuper());
-}
-
-
AstNode* Parser::ParseExprList() {
TRACE_PARSER("ParseExprList");
AstNode* expressions = ParseExpr(kAllowConst, kConsumeCascades);
@@ -7189,25 +7174,35 @@
}
-// Ensure that the expression temp is allocated for nodes that may need it.
-AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) {
+AstNode* Parser::CreateAssignmentNode(AstNode* original,
+ AstNode* rhs,
+ const String* left_ident,
+ intptr_t left_pos) {
AstNode* result = original->MakeAssignmentNode(rhs);
- if ((result == NULL) && original->IsTypeNode()) {
- const String& type_name = String::ZoneHandle(
- original->AsTypeNode()->type().ClassName());
- // TODO(tball): determine whether NoSuchMethod should be called instead.
+ if (result == NULL) {
+ String& name = String::ZoneHandle();
+ if (original->IsTypeNode()) {
+ name = Symbols::New(original->Name());
+ } else if ((left_ident != NULL) &&
+ (original->IsLiteralNode() ||
+ original->IsLoadLocalNode() ||
+ original->IsLoadStaticFieldNode())) {
+ name = left_ident->raw();
+ }
+ if (name.IsNull()) {
+ ErrorMsg(left_pos, "expression is not assignable");
+ }
result = ThrowNoSuchMethodError(original->token_pos(),
current_class(),
- type_name,
+ name,
InvocationMirror::kStatic,
InvocationMirror::kSetter);
- }
- if ((result != NULL) &&
- (result->IsStoreIndexedNode() ||
- result->IsInstanceSetterNode() ||
- result->IsStaticSetterNode() ||
- result->IsStoreStaticFieldNode() ||
- result->IsStoreLocalNode())) {
+ } else if (result->IsStoreIndexedNode() ||
+ result->IsInstanceSetterNode() ||
+ result->IsStaticSetterNode() ||
+ result->IsStoreStaticFieldNode() ||
+ result->IsStoreLocalNode()) {
+ // Ensure that the expression temp is allocated for nodes that may need it.
EnsureExpressionTemp();
}
return result;
@@ -7230,6 +7225,9 @@
} else {
ErrorMsg("identifier or [ expected after ..");
}
+ String* expr_ident =
+ Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
+ const intptr_t expr_pos = TokenPos();
expr = ParseSelectors(load_cascade_receiver, true);
// Assignments after a cascade are part of the cascade. The
@@ -7245,23 +7243,17 @@
LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
right_expr =
ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
- AstNode* assign_expr = CreateAssignmentNode(expr, right_expr);
- if (assign_expr == NULL) {
- ErrorMsg(assignment_pos,
- "left hand side of '%s' is not assignable",
- Token::Str(assignment_op));
- }
+ AstNode* assign_expr = CreateAssignmentNode(
+ expr, right_expr, expr_ident, expr_pos);
+ ASSERT(assign_expr != NULL);
let_expr->AddNode(assign_expr);
expr = let_expr;
} else {
right_expr =
ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
- AstNode* assign_expr = CreateAssignmentNode(expr, right_expr);
- if (assign_expr == NULL) {
- ErrorMsg(assignment_pos,
- "left hand side of '%s' is not assignable",
- Token::Str(assignment_op));
- }
+ AstNode* assign_expr = CreateAssignmentNode(
+ expr, right_expr, expr_ident, expr_pos);
+ ASSERT(assign_expr != NULL);
expr = assign_expr;
}
}
@@ -7277,6 +7269,8 @@
AstNode* Parser::ParseExpr(bool require_compiletime_const,
bool consume_cascades) {
TRACE_PARSER("ParseExpr");
+ String* expr_ident =
+ Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
const intptr_t expr_pos = TokenPos();
if (CurrentToken() == Token::kTHROW) {
@@ -7296,7 +7290,7 @@
return expr;
}
// Assignment expressions.
- Token::Kind assignment_op = CurrentToken();
+ const Token::Kind assignment_op = CurrentToken();
const intptr_t assignment_pos = TokenPos();
ConsumeToken();
const intptr_t right_expr_pos = TokenPos();
@@ -7309,23 +7303,17 @@
LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
AstNode* assigned_value =
ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
- AstNode* assign_expr = CreateAssignmentNode(expr, assigned_value);
- if (assign_expr == NULL) {
- ErrorMsg(assignment_pos,
- "left hand side of '%s' is not assignable",
- Token::Str(assignment_op));
- }
+ AstNode* assign_expr = CreateAssignmentNode(
+ expr, assigned_value, expr_ident, expr_pos);
+ ASSERT(assign_expr != NULL);
let_expr->AddNode(assign_expr);
return let_expr;
} else {
AstNode* assigned_value =
ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
- AstNode* assign_expr = CreateAssignmentNode(expr, assigned_value);
- if (assign_expr == NULL) {
- ErrorMsg(assignment_pos,
- "left hand side of '%s' is not assignable",
- Token::Str(assignment_op));
- }
+ AstNode* assign_expr = CreateAssignmentNode(
+ expr, assigned_value, expr_ident, expr_pos);
+ ASSERT(assign_expr != NULL);
return assign_expr;
}
}
@@ -7374,10 +7362,10 @@
} else if (IsIncrementOperator(CurrentToken())) {
Token::Kind incr_op = CurrentToken();
ConsumeToken();
+ String* expr_ident =
+ Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
+ const intptr_t expr_pos = TokenPos();
expr = ParseUnaryExpr();
- if (!IsAssignableExpr(expr)) {
- ErrorMsg("expression is not assignable");
- }
// Is prefix.
LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
Token::Kind binary_op =
@@ -7387,7 +7375,7 @@
binary_op,
expr,
new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1))));
- AstNode* store = CreateAssignmentNode(expr, add);
+ AstNode* store = CreateAssignmentNode(expr, add, expr_ident, expr_pos);
ASSERT(store != NULL);
let_expr->AddNode(store);
expr = let_expr;
@@ -7727,6 +7715,18 @@
if (left->IsPrimaryNode()) {
if (left->AsPrimaryNode()->primary().IsFunction()) {
left = LoadClosure(left->AsPrimaryNode());
+ } else if (left->AsPrimaryNode()->primary().IsTypeParameter()) {
+ if (current_block_->scope->function_level() > 0) {
+ // Make sure that the instantiator is captured.
+ CaptureInstantiator();
+ }
+ TypeParameter& type_parameter = TypeParameter::ZoneHandle();
+ type_parameter ^= ClassFinalizer::FinalizeType(
+ current_class(),
+ TypeParameter::Cast(left->AsPrimaryNode()->primary()),
+ ClassFinalizer::kFinalize);
+ ASSERT(!type_parameter.IsMalformed());
+ left = new TypeNode(primary->token_pos(), type_parameter);
} else {
// Super field access handled in ParseSuperFieldAccess(),
// super calls handled in ParseSuperCall().
@@ -7783,7 +7783,26 @@
if (primary->primary().IsFunction()) {
array = LoadClosure(primary);
} else if (primary->primary().IsClass()) {
- ErrorMsg(bracket_pos, "cannot apply index operator to class");
+ const Class& type_class = Class::Cast(primary->primary());
+ Type& type = Type::ZoneHandle(
+ Type::New(type_class, TypeArguments::Handle(),
+ primary->token_pos(), Heap::kOld));
+ type ^= ClassFinalizer::FinalizeType(
+ current_class(), type, ClassFinalizer::kCanonicalize);
+ ASSERT(!type.IsMalformed());
+ array = new TypeNode(primary->token_pos(), type);
+ } else if (primary->primary().IsTypeParameter()) {
+ if (current_block_->scope->function_level() > 0) {
+ // Make sure that the instantiator is captured.
+ CaptureInstantiator();
+ }
+ TypeParameter& type_parameter = TypeParameter::ZoneHandle();
+ type_parameter ^= ClassFinalizer::FinalizeType(
+ current_class(),
+ TypeParameter::Cast(primary->primary()),
+ ClassFinalizer::kFinalize);
+ ASSERT(!type_parameter.IsMalformed());
+ array = new TypeNode(primary->token_pos(), type_parameter);
} else {
UNREACHABLE(); // Internal parser error.
}
@@ -7830,9 +7849,23 @@
AstNode* receiver = LoadReceiver(primary->token_pos());
selector = ParseInstanceCall(receiver, name);
}
+ } else if (primary->primary().IsTypeParameter()) {
+ const String& name = String::ZoneHandle(
+ Symbols::New(primary->Name()));
+ selector = ThrowNoSuchMethodError(primary->token_pos(),
+ current_class(),
+ name,
+ InvocationMirror::kStatic,
+ InvocationMirror::kMethod);
} else if (primary->primary().IsClass()) {
- ErrorMsg(left->token_pos(),
- "must use 'new' or 'const' to construct new instance");
+ const Class& type_class = Class::Cast(primary->primary());
+ Type& type = Type::ZoneHandle(
+ Type::New(type_class, TypeArguments::Handle(),
+ primary->token_pos(), Heap::kOld));
+ type ^= ClassFinalizer::FinalizeType(
+ current_class(), type, ClassFinalizer::kCanonicalize);
+ ASSERT(!type.IsMalformed());
+ selector = new TypeNode(primary->token_pos(), type);
} else {
UNREACHABLE(); // Internal parser error.
}
@@ -7856,7 +7889,20 @@
primary->token_pos(), Heap::kOld));
type ^= ClassFinalizer::FinalizeType(
current_class(), type, ClassFinalizer::kCanonicalize);
+ ASSERT(!type.IsMalformed());
left = new TypeNode(primary->token_pos(), type);
+ } else if (primary->primary().IsTypeParameter()) {
+ if (current_block_->scope->function_level() > 0) {
+ // Make sure that the instantiator is captured.
+ CaptureInstantiator();
+ }
+ TypeParameter& type_parameter = TypeParameter::ZoneHandle();
+ type_parameter ^= ClassFinalizer::FinalizeType(
+ current_class(),
+ TypeParameter::Cast(primary->primary()),
+ ClassFinalizer::kFinalize);
+ ASSERT(!type_parameter.IsMalformed());
+ left = new TypeNode(primary->token_pos(), type_parameter);
} else if (primary->IsSuper()) {
// Return "super" to handle unary super operator calls,
// or to report illegal use of "super" otherwise.
@@ -7876,35 +7922,34 @@
AstNode* Parser::ParsePostfixExpr() {
TRACE_PARSER("ParsePostfixExpr");
- const intptr_t postfix_expr_pos = TokenPos();
- AstNode* postfix_expr = ParsePrimary();
- postfix_expr = ParseSelectors(postfix_expr, false);
+ String* expr_ident =
+ Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
+ const intptr_t expr_pos = TokenPos();
+ AstNode* expr = ParsePrimary();
+ expr = ParseSelectors(expr, false);
if (IsIncrementOperator(CurrentToken())) {
TRACE_PARSER("IncrementOperator");
Token::Kind incr_op = CurrentToken();
- if (!IsAssignableExpr(postfix_expr)) {
- ErrorMsg("expression is not assignable");
- }
ConsumeToken();
// Not prefix.
- LetNode* let_expr = PrepareCompoundAssignmentNodes(&postfix_expr);
- LocalVariable* temp = let_expr->AddInitializer(postfix_expr);
+ LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
+ LocalVariable* temp = let_expr->AddInitializer(expr);
Token::Kind binary_op =
(incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
BinaryOpNode* add = new BinaryOpNode(
- postfix_expr_pos,
+ expr_pos,
binary_op,
- new LoadLocalNode(postfix_expr_pos, temp),
- new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1))));
- AstNode* store = CreateAssignmentNode(postfix_expr, add);
+ new LoadLocalNode(expr_pos, temp),
+ new LiteralNode(expr_pos, Smi::ZoneHandle(Smi::New(1))));
+ AstNode* store = CreateAssignmentNode(expr, add, expr_ident, expr_pos);
ASSERT(store != NULL);
// The result is a pair of the (side effects of the) store followed by
// the (value of the) initial value temp variable load.
let_expr->AddNode(store);
- let_expr->AddNode(new LoadLocalNode(postfix_expr_pos, temp));
+ let_expr->AddNode(new LoadLocalNode(expr_pos, temp));
return let_expr;
}
- return postfix_expr;
+ return expr;
}
@@ -7934,8 +7979,7 @@
if (!scope_class.IsNull()) {
// First check if the type is a type parameter of the given scope class.
const TypeParameter& type_parameter = TypeParameter::Handle(
- scope_class.LookupTypeParameter(unresolved_class_name,
- type->token_pos()));
+ scope_class.LookupTypeParameter(unresolved_class_name));
if (!type_parameter.IsNull()) {
// A type parameter is considered to be a malformed type when
// referenced by a static member.
@@ -8640,8 +8684,7 @@
}
-// Resolve identifier, issue an error message if the name refers to
-// a class/interface or a type parameter. Issue an error message if
+// Resolve identifier. Issue an error message if
// the ident refers to a method and allow_closure_names is false.
// If the name cannot be resolved, turn it into an instance field access
// if we're compiling an instance method, or issue an error message
@@ -8655,15 +8698,19 @@
AstNode* resolved = NULL;
ResolveIdentInLocalScope(ident_pos, ident, &resolved);
if (resolved == NULL) {
- // Check whether the identifier is a type parameter. Type parameters
- // can never be used in primary expressions.
+ // Check whether the identifier is a type parameter.
if (!current_class().IsNull()) {
- TypeParameter& type_param = TypeParameter::Handle(
- current_class().LookupTypeParameter(ident, ident_pos));
- if (!type_param.IsNull()) {
- String& type_param_name = String::Handle(type_param.name());
- ErrorMsg(ident_pos, "illegal use of type parameter %s",
- type_param_name.ToCString());
+ TypeParameter& type_parameter = TypeParameter::ZoneHandle(
+ current_class().LookupTypeParameter(ident));
+ if (!type_parameter.IsNull()) {
+ if (current_block_->scope->function_level() > 0) {
+ // Make sure that the instantiator is captured.
+ CaptureInstantiator();
+ }
+ type_parameter ^= ClassFinalizer::FinalizeType(
+ current_class(), type_parameter, ClassFinalizer::kFinalize);
+ ASSERT(!type_parameter.IsMalformed());
+ return new TypeNode(ident_pos, type_parameter);
}
}
// Not found in the local scope, and the name is not a type parameter.
@@ -8696,10 +8743,15 @@
ErrorMsg(ident_pos, "illegal reference to method '%s'",
ident.ToCString());
}
- } else {
- ASSERT(primary->primary().IsClass());
- ErrorMsg(ident_pos, "illegal reference to class or interface '%s'",
- ident.ToCString());
+ } else if (primary->primary().IsClass()) {
+ const Class& type_class = Class::Cast(primary->primary());
+ Type& type = Type::ZoneHandle(
+ Type::New(type_class, TypeArguments::Handle(),
+ primary->token_pos(), Heap::kOld));
+ type ^= ClassFinalizer::FinalizeType(
+ current_class(), type, ClassFinalizer::kCanonicalize);
+ ASSERT(!type.IsMalformed());
+ resolved = new TypeNode(primary->token_pos(), type);
}
}
return resolved;
@@ -9552,17 +9604,12 @@
if (!ResolveIdentInLocalScope(qual_ident.ident_pos,
*qual_ident.ident,
&primary)) {
- // Check whether the identifier is a type parameter. Type parameters
- // can never be used as part of primary expressions.
+ // Check whether the identifier is a type parameter.
if (!current_class().IsNull()) {
TypeParameter& type_param = TypeParameter::ZoneHandle(
- current_class().LookupTypeParameter(*(qual_ident.ident),
- TokenPos()));
+ current_class().LookupTypeParameter(*(qual_ident.ident)));
if (!type_param.IsNull()) {
- const String& type_param_name = String::Handle(type_param.name());
- ErrorMsg(qual_ident.ident_pos,
- "illegal use of type parameter %s",
- type_param_name.ToCString());
+ return new PrimaryNode(qual_ident.ident_pos, type_param);
}
}
// This is a non-local unqualified identifier so resolve the
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-dart2dart.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698