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

Unified Diff: runtime/vm/parser.cc

Issue 10821076: - Allow parsing of external methods. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 9985)
+++ runtime/vm/parser.cc (working copy)
@@ -452,6 +452,7 @@
}
void Clear() {
has_abstract = false;
+ has_external = false;
has_final = false;
has_const = false;
has_static = false;
@@ -480,6 +481,7 @@
return kind == RawFunction::kSetterFunction;
}
bool has_abstract;
+ bool has_external;
bool has_final;
bool has_const;
bool has_static;
@@ -1065,6 +1067,7 @@
RawFunction::kSignatureFunction,
/* is_static = */ false,
/* is_const = */ false,
+ /* is_external = */ false,
parameter.name_pos));
signature_function.set_owner(current_class());
signature_function.set_result_type(result_type);
@@ -2165,6 +2168,13 @@
current_block_->statements->Add(new ReturnNode(expr_pos, expr));
} else if (IsLiteral("native")) {
ParseNativeFunctionBlock(&params, func);
+ } else if (func.is_external()) {
+ // Body of an external method contains a single throw.
+ current_block_->statements->Add(
+ new ThrowNode(TokenPos(),
+ new LiteralNode(TokenPos(),
+ String::ZoneHandle(
+ Symbols::New("External implementation missing."))), NULL));
} else {
UnexpectedToken();
}
@@ -2293,6 +2303,10 @@
ErrorMsg(method->name_pos,
"'abstract' method only allowed in class definition");
}
+ if (method->has_external && members->is_interface()) {
+ ErrorMsg(method->name_pos,
+ "'external' method only allowed in class definition");
+ }
if (members->FunctionNameExists(*method->name, method->kind)) {
ErrorMsg(method->name_pos,
@@ -2384,6 +2398,10 @@
ErrorMsg(method->name_pos,
"abstract method '%s' may not have function body",
method->name->ToCString());
+ } else if (method->has_external) {
+ ErrorMsg(method->name_pos,
+ "external method '%s' may not have function body",
+ method->name->ToCString());
} else if (method->IsConstructor() && method->has_const) {
ErrorMsg(method->name_pos,
"const constructor '%s' may not have function body",
@@ -2421,6 +2439,7 @@
} else if (CurrentToken() == Token::kSEMICOLON) {
if (members->is_interface() ||
method->has_abstract ||
+ method->has_external ||
(method->redirect_name != NULL) ||
method->IsConstructor()) {
ConsumeToken();
@@ -2432,6 +2451,7 @@
} else {
if (members->is_interface() ||
method->has_abstract ||
+ method->has_external ||
(method->redirect_name != NULL) ||
(method->IsConstructor() && method->has_const)) {
ExpectSemicolon();
@@ -2459,6 +2479,7 @@
function_kind,
method->has_static,
method->has_const,
+ method->has_external,
method_pos));
func.set_result_type(*method->type);
func.set_end_token_pos(method_end_pos);
@@ -2530,7 +2551,7 @@
class_field.set_value(Instance::Handle(Object::sentinel()));
String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
getter = Function::New(getter_name, RawFunction::kConstImplicitGetter,
- field->has_static, field->has_final,
+ field->has_static, field->has_final, false,
field->name_pos);
getter.set_result_type(*field->type);
members->AddFunction(getter);
@@ -2540,7 +2561,7 @@
if (!field->has_static) {
String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
getter = Function::New(getter_name, RawFunction::kImplicitGetter,
- field->has_static, field->has_final,
+ field->has_static, field->has_final, false,
field->name_pos);
ParamList params;
params.AddReceiver(TokenPos());
@@ -2551,7 +2572,7 @@
// Build a setter accessor for non-const fields.
String& setter_name = String::Handle(Field::SetterSymbol(*field->name));
setter = Function::New(setter_name, RawFunction::kImplicitSetter,
- field->has_static, field->has_final,
+ field->has_static, field->has_final, false,
field->name_pos);
ParamList params;
params.AddReceiver(TokenPos());
@@ -2605,6 +2626,11 @@
ConsumeToken();
member.has_abstract = true;
}
+ if ((CurrentToken() == Token::kEXTERNAL) &&
+ (LookaheadToken(1) != Token::kLPAREN)) {
+ ConsumeToken();
+ member.has_external = true;
+ }
if ((CurrentToken() == Token::kSTATIC) &&
(LookaheadToken(1) != Token::kLPAREN)) {
ConsumeToken();
@@ -2921,6 +2947,7 @@
RawFunction::kConstructor,
/* is_static = */ false,
/* is_const = */ false,
+ /* is_external = */ false,
class_desc->token_pos()));
ParamList params;
// Add implicit 'this' parameter.
@@ -3039,6 +3066,7 @@
RawFunction::kSignatureFunction,
/* is_static = */ false,
/* is_const = */ false,
+ /* is_external = */ false,
alias_name_pos));
signature_function.set_owner(alias_owner);
signature_function.set_result_type(result_type);
@@ -3468,7 +3496,7 @@
// Create a static const getter.
String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name));
getter = Function::New(getter_name, RawFunction::kConstImplicitGetter,
- is_static, is_final, name_pos);
+ is_static, is_final, false, name_pos);
getter.set_result_type(type);
top_level->functions.Add(getter);
} else if (is_final) {
@@ -3491,6 +3519,11 @@
TRACE_PARSER("ParseTopLevelFunction");
AbstractType& result_type = Type::Handle(Type::DynamicType());
const bool is_static = true;
+ bool is_external = false;
+ if (CurrentToken() == Token::kEXTERNAL) {
+ ConsumeToken();
+ is_external = true;
+ }
if (CurrentToken() == Token::kVOID) {
ConsumeToken();
result_type = Type::VoidType();
@@ -3527,7 +3560,9 @@
ParseFormalParameterList(allow_explicit_default_values, &params);
intptr_t function_end_pos = function_pos;
- if (CurrentToken() == Token::kLBRACE) {
+ if (is_external) {
+ ExpectSemicolon();
+ } else if (CurrentToken() == Token::kLBRACE) {
SkipBlock();
function_end_pos = TokenPos();
} else if (CurrentToken() == Token::kARROW) {
@@ -3542,7 +3577,7 @@
}
Function& func = Function::Handle(
Function::New(func_name, RawFunction::kRegularFunction,
- is_static, false, function_pos));
+ is_static, false, is_external, function_pos));
func.set_result_type(result_type);
func.set_end_token_pos(function_end_pos);
AddFormalParamsToFunction(&params, func);
@@ -3624,7 +3659,7 @@
Function::New(accessor_name,
is_getter? RawFunction::kGetterFunction :
RawFunction::kSetterFunction,
- is_static, false, accessor_pos));
+ is_static, false, false, accessor_pos));
func.set_result_type(result_type);
AddFormalParamsToFunction(&params, func);
top_level->functions.Add(func);
@@ -4470,6 +4505,12 @@
// a function declaration. Token position remains unchanged.
bool Parser::IsFunctionDeclaration() {
const intptr_t saved_pos = TokenPos();
+ bool is_external = false;
+ if (is_top_level_ && (CurrentToken() == Token::kEXTERNAL)) {
+ // Skip over 'external' for top-level function declarations.
+ is_external = true;
+ ConsumeToken();
+ }
if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) {
// Possibly a function without explicit return type.
ConsumeToken(); // Consume function identifier.
@@ -4488,7 +4529,8 @@
SkipToMatchingParenthesis();
if ((CurrentToken() == Token::kLBRACE) ||
(CurrentToken() == Token::kARROW) ||
- (is_top_level_ && IsLiteral("native"))) {
+ (is_top_level_ && IsLiteral("native")) ||
+ (is_external && (CurrentToken() == Token::kSEMICOLON))) {
hausner 2012/07/30 16:22:41 I don't think you need to check for the semicolon
Ivan Posva 2012/07/30 22:33:33 Done.
SetPosition(saved_pos);
return true;
}

Powered by Google App Engine
This is Rietveld 408576698