Commit bf85ca53 authored by nikolaos's avatar nikolaos Committed by Commit bot

[parser] Refactor of Parse*Statement*, part 5

This patch moves the following parsing methods to ParserBase:

- ParseDoExpression
- ParseDoWhileStatement
- ParseWhileStatement
- ParseThrowStatement

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

Review-Url: https://codereview.chromium.org/2321103002
Cr-Commit-Position: refs/heads/master@{#39326}
parent 40ba1db5
...@@ -1198,6 +1198,8 @@ class ParserBase { ...@@ -1198,6 +1198,8 @@ class ParserBase {
// Magical syntax support. // Magical syntax support.
ExpressionT ParseV8Intrinsic(bool* ok); ExpressionT ParseV8Intrinsic(bool* ok);
ExpressionT ParseDoExpression(bool* ok);
StatementT ParseDebuggerStatement(bool* ok); StatementT ParseDebuggerStatement(bool* ok);
StatementT ParseExpressionOrLabelledStatement( StatementT ParseExpressionOrLabelledStatement(
...@@ -1210,6 +1212,11 @@ class ParserBase { ...@@ -1210,6 +1212,11 @@ class ParserBase {
StatementT ParseReturnStatement(bool* ok); StatementT ParseReturnStatement(bool* ok);
StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels, StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels,
bool* ok); bool* ok);
StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
StatementT ParseThrowStatement(bool* ok);
bool IsNextLetKeyword(); bool IsNextLetKeyword();
bool IsTrivialExpression(); bool IsTrivialExpression();
...@@ -1759,7 +1766,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression( ...@@ -1759,7 +1766,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::DO: case Token::DO:
if (allow_harmony_do_expressions()) { if (allow_harmony_do_expressions()) {
BindingPatternUnexpectedToken(); BindingPatternUnexpectedToken();
return impl()->ParseDoExpression(ok); return ParseDoExpression(ok);
} }
break; break;
...@@ -4053,6 +4060,18 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic( ...@@ -4053,6 +4060,18 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic(
return impl()->NewV8Intrinsic(name, args, pos, ok); return impl()->NewV8Intrinsic(name, args, pos, ok);
} }
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseDoExpression(
bool* ok) {
// AssignmentExpression ::
// do '{' StatementList '}'
int pos = peek_position();
Expect(Token::DO, CHECK_OK);
BlockT block = ParseBlock(nullptr, CHECK_OK);
return impl()->RewriteDoExpression(block, pos, ok);
}
// Redefinition of CHECK_OK for parsing statements. // Redefinition of CHECK_OK for parsing statements.
#undef CHECK_OK #undef CHECK_OK
#define CHECK_OK CHECK_OK_CUSTOM(NullStatement) #define CHECK_OK CHECK_OK_CUSTOM(NullStatement)
...@@ -4235,9 +4254,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement( ...@@ -4235,9 +4254,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
case Token::IF: case Token::IF:
return ParseIfStatement(labels, ok); return ParseIfStatement(labels, ok);
case Token::DO: case Token::DO:
return impl()->ParseDoWhileStatement(labels, ok); return ParseDoWhileStatement(labels, ok);
case Token::WHILE: case Token::WHILE:
return impl()->ParseWhileStatement(labels, ok); return ParseWhileStatement(labels, ok);
case Token::FOR: case Token::FOR:
return impl()->ParseForStatement(labels, ok); return impl()->ParseForStatement(labels, ok);
case Token::CONTINUE: case Token::CONTINUE:
...@@ -4300,7 +4319,7 @@ ParserBase<Impl>::ParseStatementAsUnlabelled( ...@@ -4300,7 +4319,7 @@ ParserBase<Impl>::ParseStatementAsUnlabelled(
case Token::RETURN: case Token::RETURN:
return ParseReturnStatement(ok); return ParseReturnStatement(ok);
case Token::THROW: case Token::THROW:
return impl()->ParseThrowStatement(ok); return ParseThrowStatement(ok);
case Token::TRY: case Token::TRY:
return impl()->ParseTryStatement(ok); return impl()->ParseTryStatement(ok);
default: default:
...@@ -4634,6 +4653,71 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement( ...@@ -4634,6 +4653,71 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
return factory()->NewWithStatement(with_scope, expr, body, pos); return factory()->NewWithStatement(with_scope, expr, body, pos);
} }
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
auto loop = factory()->NewDoWhileStatement(labels, peek_position());
typename Types::Target target(this, loop);
Expect(Token::DO, CHECK_OK);
StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ExpressionT cond = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
// Allow do-statements to be terminated with and without
// semi-colons. This allows code such as 'do;while(0)return' to
// parse, which would not be the case if we had used the
// ExpectSemicolon() functionality here.
Check(Token::SEMICOLON);
loop->Initialize(cond, body);
return loop;
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
auto loop = factory()->NewWhileStatement(labels, peek_position());
typename Types::Target target(this, loop);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ExpressionT cond = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
loop->Initialize(cond, body);
return loop;
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
bool* ok) {
// ThrowStatement ::
// 'throw' Expression ';'
Expect(Token::THROW, CHECK_OK);
int pos = position();
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
ReportMessage(MessageTemplate::kNewlineAfterThrow);
*ok = false;
return impl()->NullStatement();
}
ExpressionT exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return impl()->NewThrowStatement(exception, pos);
}
#undef CHECK_OK #undef CHECK_OK
#undef CHECK_OK_CUSTOM #undef CHECK_OK_CUSTOM
......
...@@ -1702,6 +1702,16 @@ Expression* Parser::RewriteReturn(Expression* return_value, int pos) { ...@@ -1702,6 +1702,16 @@ Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
return return_value; return return_value;
} }
Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) {
Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
DoExpression* expr = factory()->NewDoExpression(body, result, pos);
if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
*ok = false;
return nullptr;
}
return expr;
}
Statement* Parser::ParseFunctionDeclaration(bool* ok) { Statement* Parser::ParseFunctionDeclaration(bool* ok) {
Consume(Token::FUNCTION); Consume(Token::FUNCTION);
int pos = position(); int pos = position();
...@@ -1825,26 +1835,6 @@ Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels, ...@@ -1825,26 +1835,6 @@ Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
return switch_block; return switch_block;
} }
Statement* Parser::ParseThrowStatement(bool* ok) {
// ThrowStatement ::
// 'throw' Expression ';'
Expect(Token::THROW, CHECK_OK);
int pos = position();
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
ReportMessage(MessageTemplate::kNewlineAfterThrow);
*ok = false;
return NULL;
}
Expression* exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return factory()->NewExpressionStatement(
factory()->NewThrow(exception, pos), pos);
}
TryStatement* Parser::ParseTryStatement(bool* ok) { TryStatement* Parser::ParseTryStatement(bool* ok) {
// TryStatement :: // TryStatement ::
// 'try' Block Catch // 'try' Block Catch
...@@ -2038,53 +2028,6 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { ...@@ -2038,53 +2028,6 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
} }
DoWhileStatement* Parser::ParseDoWhileStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
DoWhileStatement* loop =
factory()->NewDoWhileStatement(labels, peek_position());
ParserTarget target(this, loop);
Expect(Token::DO, CHECK_OK);
Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
Expression* cond = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
// Allow do-statements to be terminated with and without
// semi-colons. This allows code such as 'do;while(0)return' to
// parse, which would not be the case if we had used the
// ExpectSemicolon() functionality here.
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
if (loop != NULL) loop->Initialize(cond, body);
return loop;
}
WhileStatement* Parser::ParseWhileStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
ParserTarget target(this, loop);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
Expression* cond = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
if (loop != NULL) loop->Initialize(cond, body);
return loop;
}
// !%_IsJSReceiver(result = iterator.next()) && // !%_IsJSReceiver(result = iterator.next()) &&
// %ThrowIteratorResultNotAnObject(result) // %ThrowIteratorResultNotAnObject(result)
Expression* Parser::BuildIteratorNextResult(Expression* iterator, Expression* Parser::BuildIteratorNextResult(Expression* iterator,
...@@ -2959,22 +2902,6 @@ void Parser::DesugarAsyncFunctionBody(Scope* scope, ZoneList<Statement*>* body, ...@@ -2959,22 +2902,6 @@ void Parser::DesugarAsyncFunctionBody(Scope* scope, ZoneList<Statement*>* body,
scope->set_end_position(scanner()->location().end_pos); scope->set_end_position(scanner()->location().end_pos);
} }
DoExpression* Parser::ParseDoExpression(bool* ok) {
// AssignmentExpression ::
// do '{' StatementList '}'
int pos = peek_position();
Expect(Token::DO, CHECK_OK);
Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
Block* block = ParseBlock(nullptr, CHECK_OK);
DoExpression* expr = factory()->NewDoExpression(block, result, pos);
if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
*ok = false;
return nullptr;
}
return expr;
}
void Parser::ParseArrowFunctionFormalParameterList( void Parser::ParseArrowFunctionFormalParameterList(
ParserFormalParameters* parameters, Expression* expr, ParserFormalParameters* parameters, Expression* expr,
const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
......
...@@ -287,7 +287,6 @@ class Parser : public ParserBase<Parser> { ...@@ -287,7 +287,6 @@ class Parser : public ParserBase<Parser> {
bool is_generator, bool is_async, bool is_generator, bool is_async,
ZoneList<const AstRawString*>* names, bool* ok); ZoneList<const AstRawString*>* names, bool* ok);
DoExpression* ParseDoExpression(bool* ok);
Expression* ParseYieldStarExpression(bool* ok); Expression* ParseYieldStarExpression(bool* ok);
class PatternRewriter final : public AstVisitor<PatternRewriter> { class PatternRewriter final : public AstVisitor<PatternRewriter> {
...@@ -374,12 +373,7 @@ class Parser : public ParserBase<Parser> { ...@@ -374,12 +373,7 @@ class Parser : public ParserBase<Parser> {
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok); CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
Statement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels, Statement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
bool* ok); bool* ok);
DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseThrowStatement(bool* ok);
Expression* MakeCatchContext(Handle<String> id, VariableProxy* value); Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
TryStatement* ParseTryStatement(bool* ok); TryStatement* ParseTryStatement(bool* ok);
...@@ -407,7 +401,7 @@ class Parser : public ParserBase<Parser> { ...@@ -407,7 +401,7 @@ class Parser : public ParserBase<Parser> {
FunctionKind kind, FunctionBodyType type, FunctionKind kind, FunctionBodyType type,
bool accept_IN, int pos, bool* ok); bool accept_IN, int pos, bool* ok);
void RewriteDoExpression(Expression* expr, bool* ok); Expression* RewriteDoExpression(Block* body, int pos, bool* ok);
FunctionLiteral* ParseFunctionLiteral( FunctionLiteral* ParseFunctionLiteral(
const AstRawString* name, Scanner::Location function_name_location, const AstRawString* name, Scanner::Location function_name_location,
...@@ -955,6 +949,11 @@ class Parser : public ParserBase<Parser> { ...@@ -955,6 +949,11 @@ class Parser : public ParserBase<Parser> {
ZoneList<Expression*>* args, int pos, ZoneList<Expression*>* args, int pos,
bool* ok); bool* ok);
V8_INLINE Statement* NewThrowStatement(Expression* exception, int pos) {
return factory()->NewExpressionStatement(
factory()->NewThrow(exception, pos), pos);
}
V8_INLINE void AddParameterInitializationBlock( V8_INLINE void AddParameterInitializationBlock(
const ParserFormalParameters& parameters, ZoneList<Statement*>* body, const ParserFormalParameters& parameters, ZoneList<Statement*>* body,
bool is_async, bool* ok) { bool is_async, bool* ok) {
......
...@@ -200,34 +200,6 @@ PreParser::Statement PreParser::ParseSwitchStatement( ...@@ -200,34 +200,6 @@ PreParser::Statement PreParser::ParseSwitchStatement(
return Statement::Default(); return Statement::Default();
} }
PreParser::Statement PreParser::ParseDoWhileStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
Expect(Token::DO, CHECK_OK);
ParseScopedStatement(nullptr, true, CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, ok);
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
return Statement::Default();
}
PreParser::Statement PreParser::ParseWhileStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
ParseScopedStatement(nullptr, true, ok);
return Statement::Default();
}
PreParser::Statement PreParser::ParseForStatement( PreParser::Statement PreParser::ParseForStatement(
ZoneList<const AstRawString*>* labels, bool* ok) { ZoneList<const AstRawString*>* labels, bool* ok) {
// ForStatement :: // ForStatement ::
...@@ -362,22 +334,6 @@ PreParser::Statement PreParser::ParseForStatement( ...@@ -362,22 +334,6 @@ PreParser::Statement PreParser::ParseForStatement(
} }
PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
// ThrowStatement ::
// 'throw' [no line terminator] Expression ';'
Expect(Token::THROW, CHECK_OK);
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
ReportMessageAt(scanner()->location(), MessageTemplate::kNewlineAfterThrow);
*ok = false;
return Statement::Default();
}
ParseExpression(true, CHECK_OK);
ExpectSemicolon(ok);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseTryStatement(bool* ok) { PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
// TryStatement :: // TryStatement ::
// 'try' Block Catch // 'try' Block Catch
...@@ -609,18 +565,6 @@ PreParserExpression PreParser::ParseClassLiteral( ...@@ -609,18 +565,6 @@ PreParserExpression PreParser::ParseClassLiteral(
return Expression::Default(); return Expression::Default();
} }
PreParserExpression PreParser::ParseDoExpression(bool* ok) {
// AssignmentExpression ::
// do '{' StatementList '}'
Expect(Token::DO, CHECK_OK);
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
ParseStatementListItem(CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
return PreParserExpression::Default();
}
void PreParser::ParseAsyncArrowSingleExpressionBody(PreParserStatementList body, void PreParser::ParseAsyncArrowSingleExpressionBody(PreParserStatementList body,
bool accept_IN, int pos, bool accept_IN, int pos,
bool* ok) { bool* ok) {
......
...@@ -448,6 +448,7 @@ class PreParserStatement { ...@@ -448,6 +448,7 @@ class PreParserStatement {
PreParserStatementList statements() { return PreParserStatementList(); } PreParserStatementList statements() { return PreParserStatementList(); }
void set_scope(Scope* scope) {} void set_scope(Scope* scope) {}
void Initialize(PreParserExpression cond, PreParserStatement body) {}
private: private:
enum Type { enum Type {
...@@ -640,6 +641,16 @@ class PreParserFactory { ...@@ -640,6 +641,16 @@ class PreParserFactory {
return PreParserStatement::Default(); return PreParserStatement::Default();
} }
PreParserStatement NewDoWhileStatement(ZoneList<const AstRawString*>* labels,
int pos) {
return PreParserStatement::Default();
}
PreParserStatement NewWhileStatement(ZoneList<const AstRawString*>* labels,
int pos) {
return PreParserStatement::Default();
}
// Return the object itself as AstVisitor and implement the needed // Return the object itself as AstVisitor and implement the needed
// dummy method right in this class. // dummy method right in this class.
PreParserFactory* visitor() { return this; } PreParserFactory* visitor() { return this; }
...@@ -805,16 +816,10 @@ class PreParser : public ParserBase<PreParser> { ...@@ -805,16 +816,10 @@ class PreParser : public ParserBase<PreParser> {
bool default_export, bool* ok); bool default_export, bool* ok);
Statement ParseSwitchStatement(ZoneList<const AstRawString*>* labels, Statement ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
bool* ok); bool* ok);
Statement ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement ParseWhileStatement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); Statement ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement ParseThrowStatement(bool* ok);
Statement ParseTryStatement(bool* ok); Statement ParseTryStatement(bool* ok);
Expression ParseConditionalExpression(bool accept_IN, bool* ok); Expression ParseConditionalExpression(bool accept_IN, bool* ok);
Expression ParseObjectLiteral(bool* ok); Expression ParseObjectLiteral(bool* ok);
Expression ParseDoExpression(bool* ok);
V8_INLINE PreParserStatementList ParseEagerFunctionBody( V8_INLINE PreParserStatementList ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos, PreParserIdentifier function_name, int pos,
...@@ -929,6 +934,11 @@ class PreParser : public ParserBase<PreParser> { ...@@ -929,6 +934,11 @@ class PreParser : public ParserBase<PreParser> {
return return_value; return return_value;
} }
V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body,
int pos, bool* ok) {
return PreParserExpression::Default();
}
// TODO(nikolaos): The preparser currently does not keep track of labels // TODO(nikolaos): The preparser currently does not keep track of labels
// and targets. // and targets.
V8_INLINE PreParserStatement LookupBreakTarget(PreParserIdentifier label, V8_INLINE PreParserStatement LookupBreakTarget(PreParserIdentifier label,
...@@ -1258,6 +1268,11 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1258,6 +1268,11 @@ class PreParser : public ParserBase<PreParser> {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
V8_INLINE PreParserStatement NewThrowStatement(PreParserExpression exception,
int pos) {
return PreParserStatement::Jump();
}
V8_INLINE void AddParameterInitializationBlock( V8_INLINE void AddParameterInitializationBlock(
const PreParserFormalParameters& parameters, PreParserStatementList body, const PreParserFormalParameters& parameters, PreParserStatementList body,
bool is_async, bool* ok) {} bool is_async, bool* ok) {}
......
...@@ -35,9 +35,9 @@ bytecode array length: 13 ...@@ -35,9 +35,9 @@ bytecode array length: 13
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 55 S> */ B(LdaSmi), U8(100), /* 55 S> */ B(LdaSmi), U8(100),
B(Star), R(1), B(Star), R(0),
/* 42 S> */ B(LdrUndefined), R(0), /* 42 S> */ B(LdrUndefined), R(1),
B(Ldar), R(0), B(Ldar), R(1),
B(Star), R(2), B(Star), R(2),
/* 63 S> */ B(Nop), /* 63 S> */ B(Nop),
/* 73 S> */ B(Return), /* 73 S> */ B(Return),
......
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