Commit 6c2c17cd authored by nikolaos's avatar nikolaos Committed by Commit bot

[parser] Apply an adaptation of the CRTP

This patch applies an adaptation of the Curiously Recurring Template
Pattern to the parser objects.  The result is roughly:

    // Common denominator, needed to avoid cyclic dependency.
    // Instances of this template will end up with very minimal
    // definitions, ideally containing just typedefs.
    template <typename Impl>
    class ParserBaseTraits;

    // The parser base object, which should just implement pure
    // parser behavior.  The Impl parameter is the actual derived
    // class (according to CRTP), which implements impure parser
    // behavior.
    template <typename Impl>
    class ParserBase : public ParserBaseTraits<Impl> { ... };

    // And then, for each parser variant:
    class Parser;

    template <>
    class ParserBaseTraits<Parser> { ... };

    class Parser : public ParserBase<Parser> { ... };

Using the CRTP, we will ultimately achieve two goals:
(1) clean up the traits objects, but most importantly
(2) clearly separate pure/impure parser implementation and facilitate
experimentation with different parser variants.

R=adamk@chromium.org, marja@chromium.org
BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2267663002
Cr-Commit-Position: refs/heads/master@{#38819}
parent 1776fd09
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -41,24 +41,21 @@ namespace internal {
#define DUMMY ) // to make indentation work
#undef DUMMY
void PreParserTraits::ReportMessageAt(Scanner::Location source_location,
MessageTemplate::Template message,
const char* arg,
ParseErrorType error_type) {
pre_parser_->log_->LogMessage(source_location.beg_pos,
source_location.end_pos, message, arg,
error_type);
void ParserBaseTraits<PreParser>::ReportMessageAt(
Scanner::Location source_location, MessageTemplate::Template message,
const char* arg, ParseErrorType error_type) {
delegate()->log_->LogMessage(source_location.beg_pos, source_location.end_pos,
message, arg, error_type);
}
void PreParserTraits::ReportMessageAt(Scanner::Location source_location,
MessageTemplate::Template message,
const AstRawString* arg,
ParseErrorType error_type) {
void ParserBaseTraits<PreParser>::ReportMessageAt(
Scanner::Location source_location, MessageTemplate::Template message,
const AstRawString* arg, ParseErrorType error_type) {
UNREACHABLE();
}
PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) const {
PreParserIdentifier ParserBaseTraits<PreParser>::GetSymbol(
Scanner* scanner) const {
switch (scanner->current_token()) {
case Token::ENUM:
return PreParserIdentifier::Enum();
......@@ -89,8 +86,7 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) const {
}
}
PreParserExpression PreParserTraits::ExpressionFromString(
PreParserExpression ParserBaseTraits<PreParser>::ExpressionFromString(
int pos, Scanner* scanner, PreParserFactory* factory) const {
if (scanner->UnescapedLiteralMatches("use strict", 10)) {
return PreParserExpression::UseStrictStringLiteral();
......@@ -98,18 +94,16 @@ PreParserExpression PreParserTraits::ExpressionFromString(
return PreParserExpression::StringLiteral();
}
PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
return pre_parser_->ParseV8Intrinsic(ok);
PreParserExpression ParserBaseTraits<PreParser>::ParseV8Intrinsic(bool* ok) {
return delegate()->ParseV8Intrinsic(ok);
}
PreParserExpression PreParserTraits::ParseFunctionLiteral(
PreParserExpression ParserBaseTraits<PreParser>::ParseFunctionLiteral(
PreParserIdentifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
LanguageMode language_mode, bool* ok) {
return pre_parser_->ParseFunctionLiteral(
return delegate()->ParseFunctionLiteral(
name, function_name_location, function_name_validity, kind,
function_token_position, type, language_mode, ok);
}
......@@ -154,12 +148,12 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
return kPreParseSuccess;
}
PreParserExpression PreParserTraits::ParseClassLiteral(
PreParserExpression ParserBaseTraits<PreParser>::ParseClassLiteral(
Type::ExpressionClassifier* classifier, PreParserIdentifier name,
Scanner::Location class_name_location, bool name_is_strict_reserved,
int pos, bool* ok) {
return pre_parser_->ParseClassLiteral(classifier, name, class_name_location,
name_is_strict_reserved, pos, ok);
return delegate()->ParseClassLiteral(classifier, name, class_name_location,
name_is_strict_reserved, pos, ok);
}
......@@ -1280,13 +1274,13 @@ PreParserExpression PreParser::ParseDoExpression(bool* ok) {
return PreParserExpression::Default();
}
void PreParserTraits::ParseAsyncArrowSingleExpressionBody(
void ParserBaseTraits<PreParser>::ParseAsyncArrowSingleExpressionBody(
PreParserStatementList body, bool accept_IN,
Type::ExpressionClassifier* classifier, int pos, bool* ok) {
Scope* scope = pre_parser_->scope();
Scope* scope = delegate()->scope();
scope->ForceContextAllocation();
PreParserExpression return_value = pre_parser_->ParseAssignmentExpression(
PreParserExpression return_value = delegate()->ParseAssignmentExpression(
accept_IN, classifier, CHECK_OK_CUSTOM(Void));
body->Add(PreParserStatement::ExpressionStatement(return_value), zone());
......
......@@ -585,13 +585,12 @@ struct PreParserFormalParameters : FormalParametersBase {
class PreParser;
class PreParserTraits {
template <>
class ParserBaseTraits<PreParser> {
public:
struct Type {
// TODO(marja): To be removed. The Traits object should contain all the data
// it needs.
typedef PreParser* Parser;
typedef ParserBaseTraits<PreParser> PreParserTraits;
struct Type {
// PreParser doesn't need to store generator variables.
typedef void GeneratorVariable;
......@@ -618,7 +617,12 @@ class PreParserTraits {
typedef PreParserFactory Factory;
};
explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
// TODO(nikolaos): The traits methods should not need to call methods
// of the implementation object.
PreParser* delegate() { return reinterpret_cast<PreParser*>(this); }
const PreParser* delegate() const {
return reinterpret_cast<const PreParser*>(this);
}
// Helper functions for recursive descent.
bool IsEval(PreParserIdentifier identifier) const {
......@@ -989,9 +993,6 @@ class PreParserTraits {
inline PreParserExpression RewriteYieldStar(PreParserExpression generator,
PreParserExpression expression,
int pos);
private:
PreParser* pre_parser_;
};
......@@ -1007,7 +1008,11 @@ class PreParserTraits {
// rather it is to speed up properly written and correct programs.
// That means that contextual checks (like a label being declared where
// it is used) are generally omitted.
class PreParser : public ParserBase<PreParserTraits> {
class PreParser : public ParserBase<PreParser> {
// TODO(nikolaos): This should not be necessary. It will be removed
// when the traits object stops delegating to the implementation object.
friend class ParserBaseTraits<PreParser>;
public:
typedef PreParserIdentifier Identifier;
typedef PreParserExpression Expression;
......@@ -1020,8 +1025,8 @@ class PreParser : public ParserBase<PreParserTraits> {
PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory,
ParserRecorder* log, uintptr_t stack_limit)
: ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL,
ast_value_factory, log, this),
: ParserBase<PreParser>(zone, scanner, stack_limit, NULL,
ast_value_factory, log),
use_counts_(nullptr) {}
// Pre-parse the program from the character stream; returns true on
......@@ -1075,8 +1080,6 @@ class PreParser : public ParserBase<PreParserTraits> {
int* use_counts);
private:
friend class PreParserTraits;
static const int kLazyParseTrialLimit = 200;
// These types form an algebra over syntactic categories that is just
......@@ -1153,27 +1156,24 @@ class PreParser : public ParserBase<PreParserTraits> {
int* use_counts_;
};
void PreParserTraits::MaterializeUnspreadArgumentsLiterals(int count) {
void ParserBaseTraits<PreParser>::MaterializeUnspreadArgumentsLiterals(
int count) {
for (int i = 0; i < count; ++i) {
pre_parser_->function_state_->NextMaterializedLiteralIndex();
delegate()->function_state_->NextMaterializedLiteralIndex();
}
}
PreParserExpression PreParserTraits::SpreadCall(PreParserExpression function,
PreParserExpressionList args,
int pos) {
return pre_parser_->factory()->NewCall(function, args, pos);
PreParserExpression ParserBaseTraits<PreParser>::SpreadCall(
PreParserExpression function, PreParserExpressionList args, int pos) {
return delegate()->factory()->NewCall(function, args, pos);
}
PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
PreParserExpressionList args,
int pos) {
return pre_parser_->factory()->NewCallNew(function, args, pos);
PreParserExpression ParserBaseTraits<PreParser>::SpreadCallNew(
PreParserExpression function, PreParserExpressionList args, int pos) {
return delegate()->factory()->NewCallNew(function, args, pos);
}
void PreParserTraits::ParseArrowFunctionFormalParameterList(
void ParserBaseTraits<PreParser>::ParseArrowFunctionFormalParameterList(
PreParserFormalParameters* parameters, PreParserExpression params,
const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
const Scope::Snapshot& scope_snapshot, bool* ok) {
......@@ -1181,42 +1181,41 @@ void PreParserTraits::ParseArrowFunctionFormalParameterList(
// lists that are too long.
}
PreParserExpression PreParserTraits::ParseAsyncFunctionExpression(bool* ok) {
return pre_parser_->ParseAsyncFunctionExpression(ok);
PreParserExpression ParserBaseTraits<PreParser>::ParseAsyncFunctionExpression(
bool* ok) {
return delegate()->ParseAsyncFunctionExpression(ok);
}
PreParserExpression PreParserTraits::ParseDoExpression(bool* ok) {
return pre_parser_->ParseDoExpression(ok);
PreParserExpression ParserBaseTraits<PreParser>::ParseDoExpression(bool* ok) {
return delegate()->ParseDoExpression(ok);
}
void PreParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
bool* ok) {
pre_parser_->ValidateExpression(classifier, ok);
void ParserBaseTraits<PreParser>::RewriteNonPattern(
Type::ExpressionClassifier* classifier, bool* ok) {
delegate()->ValidateExpression(classifier, ok);
}
PreParserExpression PreParserTraits::RewriteAwaitExpression(
PreParserExpression ParserBaseTraits<PreParser>::RewriteAwaitExpression(
PreParserExpression value, int pos) {
return value;
}
ZoneList<PreParserExpression>* PreParserTraits::GetNonPatternList() const {
return pre_parser_->function_state_->non_patterns_to_rewrite();
ZoneList<PreParserExpression>* ParserBaseTraits<PreParser>::GetNonPatternList()
const {
return delegate()->function_state_->non_patterns_to_rewrite();
}
ZoneList<typename PreParserTraits::Type::ExpressionClassifier::Error>*
PreParserTraits::GetReportedErrorList() const {
return pre_parser_->function_state_->GetReportedErrorList();
ZoneList<
typename ParserBaseTraits<PreParser>::Type::ExpressionClassifier::Error>*
ParserBaseTraits<PreParser>::GetReportedErrorList() const {
return delegate()->function_state_->GetReportedErrorList();
}
Zone* PreParserTraits::zone() const {
return pre_parser_->function_state_->scope()->zone();
Zone* ParserBaseTraits<PreParser>::zone() const {
return delegate()->function_state_->scope()->zone();
}
PreParserExpression PreParserTraits::RewriteYieldStar(
PreParserExpression ParserBaseTraits<PreParser>::RewriteYieldStar(
PreParserExpression generator, PreParserExpression expression, int pos) {
return PreParserExpression::Default();
}
......@@ -1240,22 +1239,21 @@ PreParserStatementList PreParser::ParseEagerFunctionBody(
return PreParserStatementList();
}
PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
PreParserStatementList ParserBaseTraits<PreParser>::ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos,
const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
return pre_parser_->ParseEagerFunctionBody(function_name, pos, parameters,
kind, function_type, ok);
return delegate()->ParseEagerFunctionBody(function_name, pos, parameters,
kind, function_type, ok);
}
PreParserExpression PreParserTraits::CloseTemplateLiteral(
PreParserExpression ParserBaseTraits<PreParser>::CloseTemplateLiteral(
TemplateLiteralState* state, int start, PreParserExpression tag) {
if (IsTaggedTemplate(tag)) {
// Emulate generation of array literals for tag callsite
// 1st is array of cooked strings, second is array of raw strings
pre_parser_->function_state_->NextMaterializedLiteralIndex();
pre_parser_->function_state_->NextMaterializedLiteralIndex();
delegate()->function_state_->NextMaterializedLiteralIndex();
delegate()->function_state_->NextMaterializedLiteralIndex();
}
return EmptyExpression();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment